java中的地图问题

RN.*_*RN. 2 java collections hashmap

我有一个Hashmap,它有X个元素,
我需要将这个地图移动到另一个地图
这就是我的代码的样子

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();
Run Code Online (Sandbox Code Playgroud)

我观察的是 - originMapSize不等于destMapSize

看来,当我们将元素放在destMap中时,一些元素被覆盖了

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

Jon*_*eet 8

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

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

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

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

第一个键(a)明显没有问题.第二个key(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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我机器上的输出:

Adding a
Adding b
1
Run Code Online (Sandbox Code Playgroud)

您可能无法获得输出 - 这取决于:

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

它甚至可能在不同的运行中有所不同.