java - java中的 map 问题

标签 java collections hashmap

我有一个包含 X 个元素的 HashMap
我需要将此 map 移至另一张 map
这就是我的代码的样子

Map originMap = initialize();
Map destMap = new Hashmap ();  

int originMapSize = originMap.size(); 
Set<Map.Entry<K, V>> entries = originMap.entrySet();
for (Map.Entry<K, Y> mapEntry : entries) {
 K key = mapEntry.getKey();
 V value = mapEntry.getValue();
 destMap.put (key,value);
}  

// Shouldnt this be equal to originMapSize ????
int destMapSize = destMap.size();

我观察到的是 - originMapSize 不等于 destMapSize

似乎当我们将元素放入 destMap 时,某些元素被覆盖

我们已经重写了 hashCode 和 equals 方法 - 这是一个可疑的实现。
但是,如果 originMap 允许添加元素,为什么 destinationMap 不添加新元素并覆盖现有元素?

最佳答案

如果 equals 方法不对称,则可能会发生这种情况。假设有两个键 a 和 b:

  • a.hashCode() == b.hashCode()
  • a.equals(b) 返回 false
  • b.equals(a) 返回 true

然后假设 HashMap 实现通过为每个具有与新键相同哈希码的现有键调用 existingKey.equals(newKey) 来搜索现有键。

现在假设我们最初按照 { a, b } 的顺序添加它们。

第一个键(a)显然没有任何问题。第二个键 (b) 插入最终调用 a.equals(b) - 这是错误的,所以我们得到两个键。

现在构建第二个 HashMap,我们最终可能会以 { b, a } 的顺序获取条目。

这次我们首先添加 b,这很好...但是当我们插入第二个键 (a) 时,我们最终会调用 b.equals (a),返回 true,因此我们覆盖该条目。

这可能不是正在发生的事情,但它可以解释一些事情 - 并显示不对称equals方法的危险。

编辑:这是一个简短但完整的程序,演示了这种情况。 (ab 的具体细节可能不同,但不对称性是相同的。)

import java.util.*;

public class Test {

    private final String name;

    public Test(String name)
    {
        this.name = name;
    }

    public static void main(String[] args)
    {
        Map<Test, String> firstMap = new HashMap<Test, String>();

        Test a = new Test("a");
        Test b = new Test("b");

        firstMap.put(b, "b");
        firstMap.put(a, "a");

        Map<Test, String> secondMap = new HashMap<Test, String>();
        for (Map.Entry<Test, String> entry : firstMap.entrySet())
        {
            System.out.println("Adding " + entry.getKey().name);
            secondMap.put(entry.getKey(), entry.getValue());
        }
        System.out.println(secondMap.size());
    }

    @Override public int hashCode()
    {
        return 0;
    }

    @Override public boolean equals(Object other)
    {
        return this.name.equals("b");
    }
}

我的机器上的输出:

Adding a
Adding b
1

您可能无法以这种方式获得输出 - 这取决于:

  • 调用 equals 的方式(candidateKey.equals(newKey) 或反之亦然)
  • 从集合中返回条目的顺序

它甚至可能在不同的运行中以不同的方式工作。

关于java - java中的 map 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6962477/

相关文章:

java - Deorg.apache.xerces.parsers.XIncludeAwareParserConfiguration无法转换为org.apache.xerces.xni.parser.XMLParserConfiguration

java - 使用动态类引用时抑制警告

java - TestNG 与 selenium 驱动工厂并行执行

java - 为单个和多个对象创建对象容器

java - HashMap 中的内容适当的数据

java - 如何创建一个流来模拟初始化为 1 + 外循环索引的嵌套循环的行为

java - 为什么 java hashmap 在计数为 8 时对 bin 进行树形化,而在计数为 6 时对 bin 进行树形化?

java - 如何在调用 HashSet.add() 时使 HashSet<T> 调用 T.equals(Object )

java - 在 Android 设备上使用 LibGDX 切换屏幕很慢

java - 拒绝 Tomcat 连接的 Netbeans 调试