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

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

for(Entry e1: map.entrySet()) { for(Entry 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的解决方案。 我希望这有助于更好地解释事情。

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

您可以使用System.identityHashCode(x)订购密钥

 for(Map.Entry entry1: map.entrySet()) { Key key1 = entry1.getKey(); int hash1 = System.identityHashCode(key1); Value value1 = entry1.getValue(); for(Map.Entry entry2: map.entrySet()) { Key key2 = entry2.getKey(); if (key1 > System.identityHashCode(key2)) continue; Value value2 = entry1.getValue(); // compare value1 and value2; } } 

这个解决方案怎么样:

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

尝试

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

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

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

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

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

 Set values = new HashSet(); for (String value : map.values()) { if (!values.add(value)) { return true; } } return false; 
 public static boolean compareStringHashMaps(Map expectedMap, Map 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; 

}

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

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

希望这可以帮助。