【问题标题】:Remove duplicate values from HashMap in Java从 Java 中的 HashMap 中删除重复值
【发布时间】:2013-07-22 15:45:23
【问题描述】:

我有一个重复值的地图:

("A", "1");
("B", "2");
("C", "2");
("D", "3");
("E", "3");

我想在地图上有

("A", "1");
("B", "2");
("D", "3");

你知道如何去除重复值吗?

目前,我收到“java.util.ConcurrentModificationException”错误。

谢谢。

public static void main(String[] args) {

    HashMap<String, String> map = new HashMap<String, String>();
    map.put("A", "1");
    map.put("B", "2");
    map.put("C", "2");
    map.put("D", "3");
    map.put("E", "3");

    Set<String> keys = map.keySet(); // The set of keys in the map.

    Iterator<String> keyIter = keys.iterator();

    while (keyIter.hasNext()) {
        String key = keyIter.next();
        String value = map.get(key);

        System.out.println(key + "\t" + value);

        String nextValue = map.get(key);

        if (value.equals(nextValue)) {
            map.remove(key);
        }
    }
    System.out.println(map);
}

【问题讨论】:

  • 你为什么保留B而忽略C?请记住,HashMap 不会保持插入元素的顺序。
  • 你能说出具体的要求吗?看起来你想要独特的价值。 HashMap 可以给你唯一的键。反转键和值对你来说就足够了吗?
  • @RohitJain +1 这就是问题!

标签: java hashmap duplicates


【解决方案1】:

做一个反向HashMap!

HashMap<String, String> map = new HashMap<String, String>();
Set<String> keys = map.keySet(); // The set of keys in the map.

Iterator<String> keyIter = keys.iterator();

while (keyIter.hasNext()) {
    String key = keyIter.next();
    String value = map.get(key);
    map.put(value, key);
}

现在您有了 hashMap,您需要将其反转或打印出来。

无论如何不要在迭代 hashMap 时删除。将值保存在列表中并在外部循环中删除它们

【讨论】:

  • 保留哪个元素仍然是随机的(因为 HashMap 的顺序是未定义的),但如果这没问题,这很好。
  • @Heuster 我同意,但他没有说这是个问题
  • @NoIdeaForName 为什么有 map.add() 而没有 map.put()
  • @bot13 不能说我记得这是否有原因,那是 6 年前的事了。也适用于put
  • 只有key和value的类型相同才有可能
【解决方案2】:

假设您使用 Java 8,则可以使用 Stream API 和将存储现有值的 Set&lt;String&gt; 来完成:

Map<String, String> map = new HashMap<>();
map.put("A", "1");
...
System.out.printf("Before: %s%n", map);

// Set in which we keep the existing values
Set<String> existing = new HashSet<>();
map = map.entrySet()
    .stream()
    .filter(entry -> existing.add(entry.getValue()))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.printf("After: %s%n", map);     

输出:

Before: {A=1, B=2, C=2, D=3, E=3}
After: {A=1, B=2, D=3}

注意:严格来说,过滤器的谓词不应该是有状态,它应该是无状态,正如@987654322 中提到的那样@ 以确保即使我们使用并行流,结果仍保持确定性正确。但是在这里,我假设您不打算使用并行流,因此这种方法仍然有效。

【讨论】:

  • 严格来说,流不应该与副作用过滤器一起使用。
  • @GraemeMoss 没错,我加了一条评论以避免误用/误解
  • 您可以将 .filter() 替换为 .distinct()
【解决方案3】:
    Map<String,Object> mapValues = new HashMap<String,Object>(5);
    mapValues.put("1", "TJ");
    mapValues.put("2", "Arun");
    mapValues.put("3", "TJ");
    mapValues.put("4", "Venkat");
    mapValues.put("5", "Arun");

    Collection<Object> list = mapValues.values();
    for(Iterator<Object> itr = list.iterator(); itr.hasNext();)
    {
        if(Collections.frequency(list, itr.next())>1)
        {
            itr.remove();
        }
    }

【讨论】:

  • 一些解释或链接会有所帮助。特别是如果被问到为什么需要抛出一些异常。
【解决方案4】:

ConcurrentModificationException 发生了,因为您正在从map 中删除

  if (value.equals(nextValue)) {
            map.remove(key);
        }

你必须从iterator删除

if (value.equals(nextValue)) {
            keyIter.remove(key);
        }

来到重复条目问题,很简单:Find duplicate values in Java Map?

【讨论】:

  • 好吧,如果你看清楚他的代码,这并不能真正解决他的问题。
  • 这段代码是错误的,它不会编译,也没有解决问题。
  • 迭代器,Iterator&lt;String&gt; keyIter = keys.iterator();
  • keyIter.remove(key) 是什么?
  • @TheNewIdiot :这避免了异常The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.
【解决方案5】:

这可以使用 Java 8 完成。需要流的概念。伪代码, 是流()。过滤器()。收集()。 如果初始映射:{A=1, B=2, C=2, D=3, E=3}。那么删除重复项后所需的答案是 {A=1, B=2, D=3} 。

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class RemoveDuplicates1 {
   public static void main(String[] args) {

        //Initial Map : {A=1, B=2, C=2, D=3, E=3}
        //After =>  {A=1, B=2, D=3} 

      Map<String , String > map = new HashMap<>();
        map.put("A", "1");
        map.put("B", "2");
        map.put("C", "2");
        map.put("D", "3");
        map.put("E", "3");

        System.out.printf("before :   " +map );
        System.out.println("\n");

        Set<String> set = new  HashSet<>();

        map = map.entrySet().stream()
                .filter(entry -> set.add(entry.getValue()))
                .collect(Collectors.toMap(Map.Entry :: getKey ,  Map.Entry :: getValue));
        System.out.printf("after => " + map);

   }
}

【讨论】:

    【解决方案6】:

    如果这是您经常需要的,那么 apache 的 commons.collections DualHashBidiMap calss 将为您提供更多帮助,而不是使用 HashMap

    【讨论】:

      【解决方案7】:
      public static void main(String[] args) {
          Map<String, String> map = new HashMap<>();
          map.put("A", "1");
          map.put("B", "2");
          map.put("C", "2");
          map.put("D", "3");
          map.put("E", "3");
          System.out.println("Initial Map : " + map);
          for (String s : new ConcurrentHashMap<>(map).keySet()) {
              String value = map.get(s);
              for (Map.Entry<String, String> ss : new ConcurrentHashMap<>(map)
                      .entrySet()) {
                  if (s != ss.getKey() && value == ss.getValue()) {
                      map.remove(ss.getKey());
                  }
              }
          }
          System.out.println("Final Map : " + map);
      }
      

      【讨论】:

        【解决方案8】:

        这可以通过将你的 hashmap 放入 arraylist 来轻松完成。 这个arraylist是hashmap类型的。

        ArrayList<HashMap<String, String>> mArrayList=new ArrayList<>();
        HashMap<String, String> map=new HashMap<>();
        map.put("1", "1");
                mArrayList.add(map);
                map=new HashMap<>();
                map.put("1", "1"); 
                mArrayList.add(map);
                map=new HashMap<>();
                map.put("1", "2");
                mArrayList.add(map);
                map=new HashMap<>();
                map.put("1", "3");
                mArrayList.add(map);
                map=new HashMap<>();
                map.put("1", "2");
                mArrayList.add(map);
        
        for(int i=0;i<mArrayList.size();i++)
                {
                    temp=mArrayList.get(i).get("1");
                    for(int k=i+1;k<mArrayList.size();k++)
                    {
                        if(temp.equals(mArrayList.get(k).get("1")))
                        {
                            mArrayList.remove(k); 
                        } 
                    }
        
                }
        

        现在打印您的数组列表...从哈希图中轻松删除所有重复值...这是删除重复的最简单方法

        【讨论】:

          【解决方案9】:

          这将有助于从地图中删除重复值。

              Map<String, String> myMap = new TreeMap<String, String>();
              myMap.put("1", "One");
              myMap.put("2", "Two");
              myMap.put("3", "One");
              myMap.put("4", "Three");
              myMap.put("5", "Two");
              myMap.put("6", "Three");
          
              Set<String> mySet = new HashSet<String>();
          
              for (Iterator itr = myMap.entrySet().iterator(); itr.hasNext();)
              {
                  Map.Entry<String, String> entrySet = (Map.Entry) itr.next();
          
                  String value = entrySet.getValue();
          
                  if (!mySet.add(value))
                  {
                      itr.remove();               
                  }
              }
          

          System.out.println("mymap :" + mymap);

          输出:

          我的地图:{1=一,2=二,4=三}

          【讨论】:

            【解决方案10】:

            如果您只是想删除 concurrentModification 异常,那么只需将您的 HashMap 替换为 ConcurrentHashMap。

            要了解更多关于 ConcurrentHashMap 的信息,请查看here

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-03-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-06-26
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多