7

我目前正在使用 2 个 for 循环来比较所有条目,但我得到了重复的比较。因为 HashMap 没有排序,所以我不知道如何消除已经进行的比较。例如,我有类似的东西:

    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 的解决方案展开思考。我希望这有助于更好地解释事情。

4

7 回答 7

5

如果您不小心,消除重复项的成本至少会高于键的冗余比较成本。

您可以使用订购钥匙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;
   }
}
于 2013-01-07T09:23:32.270 回答
4

这个解决方案怎么样:

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])) {
      // ...
    }
  }
}
于 2013-01-07T03:19:23.230 回答
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 中的键是没有意义的,它们总是不相等的。那就是我们只能迭代/比较值

于 2013-01-07T03:05:08.290 回答
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;
于 2013-01-08T05:23:50.543 回答
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;

}

于 2017-02-25T01:32:59.803 回答
0

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

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


于 2019-10-01T07:42:16.270 回答
-1

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

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

希望这可以帮助。

于 2013-01-07T02:58:27.880 回答