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不会添加新元素并覆盖现有元素呢?
如果equals方法不对称,可能会发生这种情况.假设有两个键a和b,这样:
a.hashCode() == b.hashCode()a.equals(b) 返回falseb.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方法的危险.
编辑:这是一个简短但完整的程序,展示了这种情况.(确切的细节a和b可能不一样,但不对称是.)
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)反之亦然)它甚至可能在不同的运行中有所不同.