使用Java,如何在不重复比较的情况下将HashMap中的每个条目与同一HashMap中的每个其他条目进行比较?

时间:2013-01-07 02:48:37

标签: java hashmap iteration

我目前正在使用2 for循环来比较所有条目,但我得到重复的比较。因为HashMaps没有订购,我无法弄清楚如何消除已经进行的比较。例如,我有类似的东西:

    for(Entry<String, String> e1: map.entrySet())
    { 
        for(Entry<String, String> e2: map.entrySet())
        {    
          if (e1.getKey() != e2.getKey())
            {
           //compare e1.getValue() to e2.getValue() 
            }
        }
     }

这个问题是第一个条目将与第二个条目进行比较,然后是第三个条目,依此类推。但是第二个条目将再次与第一个条目进行比较,依此类推。然后将第三个条目与第一个条目进行比较,然后是第二个条目,然后是第四个条目,等等。是否有更好的方法来迭代HashMaps以避免进行重复比较?

其他信息:

为了更具体,希望能回答你的问题,我所拥有的HashMap是存储文件名(密钥)和文件内容(值) - 只是文本文件。通过遍历包含我想要比较的文件的目录来填充HashMap。那么我正在做的是通过一些算法运行成对的文件来确定每对文件之间的相似性。我不需要将文件1与文件2进行比较,然后再将文件2与文件1进行比较,因为我只需要比较2个文件一次。但我确实需要将每个文件与其他文件进行一次比较。我是使用HashMaps的全新人选。 agim在下面的回答可能只适用于我的目的。但我也会尝试围绕Evgeniy Dorofeev和Peter Lawrey的解决方案。我希望这有助于更好地解释事情。

7 个答案:

答案 0 :(得分:4)

如果你不小心,消除重复的成本可能高于密钥冗余比较的成本。

您可以使用System.identityHashCode(x)

订购密钥
for(Map.Entry<Key, Value> entry1: map.entrySet()) {
   Key key1 = entry1.getKey();
   int hash1 = System.identityHashCode(key1);
   Value value1 = entry1.getValue();
   for(Map.Entry<Key, Value> entry2: map.entrySet()) {
       Key key2 = entry2.getKey();
       if (key1 > System.identityHashCode(key2)) continue;

       Value value2 = entry1.getValue();
       // compare value1 and value2;
   }
}

答案 1 :(得分:3)

这个解决方案怎么样:

String[] values = map.values().toArray(new String[map.size()]);
for (int i = 0; i < values.length; i++) {
  for (int j = i+1; j<values.length; j++) {
    if (values[i].equals(values[j])) {
      // ...
    }
  }
}

答案 2 :(得分:1)

尝试

    HashMap<Object, Object> map = new HashMap<>();
    Iterator<Entry<Object, Object>> i = map.entrySet().iterator();
    while (i.hasNext()) {
        Entry next = i.next();
        i.remove();
        for (Entry e : map.entrySet()) {
            e.equals(next);
        }
    }

请注意,比较HashMap中的键总是不相等是没有意义的。那就是我们只能迭代/比较值

答案 3 :(得分:0)

如果我理解正确,你只想知道地图的值是否有任何重复?如果是这样的话:

Set<String> values = new HashSet<String>(map.values());
boolean hasDuplicates = values.size() != map.size();

如果您在找到第一个副本后踢出来,可以提高效率:

Set<String> values = new HashSet<String>();
for (String value : map.values()) {
  if (!values.add(value)) {
    return true;
  }
}
return false;

答案 4 :(得分:0)

public static boolean compareStringHashMaps(Map<String, String> expectedMap, Map<String, String> actualMap) throws Exception
{
    logger.info("## CommonFunctions | compareStringHashMaps() ## ");
        Iterator iteratorExpectedMap = expectedMap.entrySet().iterator();
        Iterator iteratorActualMap = actualMap.entrySet().iterator();
        boolean flag = true;
        while (iteratorExpectedMap.hasNext() && iteratorActualMap.hasNext()){
            Map.Entry expectedMapEntry = (Map.Entry) iteratorExpectedMap.next();
            Map.Entry actualMapEntry = (Map.Entry) iteratorActualMap.next();
            if(!expectedMapEntry.getKey().toString().trim().equals(actualMapEntry.getKey().toString().trim()))
            {   
                flag = false;
                break;
            }
            else if (!expectedMapEntry.getValue().toString().trim().equals(actualMapEntry.getValue().toString().trim()))
            {
                flag = false;
                break;
            }
        }   
        return flag;

}

答案 5 :(得分:0)

考虑到HashMap的条目是Integer。 这将返回HashMap中的最大条目。

int maxNum = 0;
for (Object a: hashMap.keySet()) {
  if ((int)hashMap.get(a) > maxNum) {
      maxNum = (int)hashMap.get(a);
  }
}


答案 6 :(得分:-1)

您可以尝试使用2D结果数组。如果已填充结果,则不要再次执行比较。这也有利于存储结果供以后使用。

因此,对于int结果,您将看到类似这样的内容:Integer[][] results = new Integer[map.entrySet().size()][map.entrySet().size()];这会将数组初始化为空值,并允许您在比较之前检查现有结果。这里需要注意的一件重要事情是,每个比较结果应该存储在数组中两次,但与自身的比较除外。例如索引1和索引2之间的比较应存储在results[1][2]result[2][1]

希望这有帮助。