在求职面试中我问过这个问题,我仍然不知道答案,所以在这里问一下。让我们说key对象的hashCode()返回一个固定的整数,所以HashMap看起来像LinkedList。
如何找到重复的元素并用map中的新值替换?
e.g。如果按照下面列出的顺序执行1001次投注,
放(1000,1000),放(1,1),放(2,2),放(3,3)....放(999,999),放(1000,1000)
是否会一直遍历地图结束,然后在执行最后一次放置(1000,1000)时将新的插入到头部?
OR
Map还有其他方法可以找到并替换重复的键吗?
答案 0 :(得分:1)
第一种情况是正确的。
在hashCode()
为所有键返回相同哈希值的情况下。在java HashMap
中,Key和Value都作为Map.Entry
对象存储在存储桶中。在地图中执行第二次或更进一步的put()
操作时,它将遍历所有元素以检查密钥是否已存在于Map
中。如果未找到密钥,则新的密钥和值对将添加到链接列表中。如果在列表中找到Key,则更新该对的值。
有关java HashMap
工作的详细说明:How HashMap works in Java
获取此示例代码并在调试模式下运行,并观察新Key和Value对如何插入Map中。
在课程中,您需要hashCode()
(我们想要控制为Node
生成哈希码的方式),toString()
(只是为了输出Node
值在SOUT中)和equals()
(基于Node
成员变量Integer的值来定义键的相等性,用于更新值。)使它工作的方法。
public class HashMapTest {
static class Node {
Integer n;
public Node(int n) {
this.n = n;
}
@Override
public int hashCode() {
return n%3;
}
@Override
public boolean equals(Object object) {
Node node = (Node)object;
return this.n.equals(node.n);
}
@Override
public String toString() {
return n.toString();
}
}
public static void main(String[] args) {
Map<Node, String> map = new HashMap<>();
for (int i = 0; i<6; i++) {
map.put(new Node(i), ""+i); // <-- Debug Point
}
map.put(new Node(0), "xxx");
} // <-- Debug Point
}
地图中的第一个3
条目:(哈希码为n%3)
还有三个值:(哈希码是n%3)
现在不要对节点的排序感到困惑,我已经在java 1.8上执行了它们,而HashMap
使用了TreeNode
,这是一个根据代码文档实现的Red-Black树。 在不同版本的java中可能会有所不同。
现在让我们更新密钥0
的价值:
答案 1 :(得分:1)
当哈希码相同时,哈希映射使用equals方法比较对象。
例如,假设你在哈希映射中放了一堆元素:
put(1000,1000), put(1,1), put( 2, 2), put ( 3,3 ) ....put(999,999)
然后你这样做:
put(1000,1000 )
1000已经在地图中,哈希码是相同的,它在equals方法上也是一样的,所以元素将被替换,不需要进一步迭代。
现在,如果你这样做:
put(1234, 1234)
1234尚未出现在地图中。由于固定的哈希码,所有元素都在链表中。哈希映射将迭代元素,使用equals进行比较。对于所有元素都将为false,将到达列表的末尾,并且将附加条目。
答案 2 :(得分:1)
JDK实现随时间而变化!
在JDK8中,如果hashCode()是常量值,则实现会创建一个树而不是链接列表,以防止DDOS攻击1。