Java HashMap冲突示例不起作用
我的理解是,Java对HashMap的实现使用“bucket”,它指向一个值列表来处理冲突,并且只有当键的hashCode()和对象的equals()对于被添加的对象及其冲突的对象都相同时,对象才会被覆盖 我尝试使用HashMap来查看碰撞行为,但无论我做什么,它似乎总是覆盖 我在这里做错了什么(注意我故意将“count”从hashCode和equals方法中漏掉)Java HashMap冲突示例不起作用,java,hashmap,collision,Java,Hashmap,Collision,我的理解是,Java对HashMap的实现使用“bucket”,它指向一个值列表来处理冲突,并且只有当键的hashCode()和对象的equals()对于被添加的对象及其冲突的对象都相同时,对象才会被覆盖 我尝试使用HashMap来查看碰撞行为,但无论我做什么,它似乎总是覆盖 我在这里做错了什么(注意我故意将“count”从hashCode和equals方法中漏掉) hashmap中的键是散列的,而不是值。在本例中,您正在调用put(key,node),并且key是常量,因此第二个put将覆盖第
hashmap中的键是散列的,而不是值。在本例中,您正在调用
put(key,node)
,并且key是常量,因此第二个put将覆盖第一个。如果节点是键,那么您将有两个条目。哈希映射中的键是散列的,而不是值。在本例中,您正在调用put(key,node)
,并且key是常量,因此第二个put将覆盖第一个。如果节点是键,那么您将有两个条目。您应该查看键而不是值。您应该查看键而不是值。如果您阅读,您将注意到put()
方法定义如下
put(对象键、对象值)
将指定的值与此映射中的指定键相关联
使用同一个键调用put()
两次时,它将覆盖与该键关联的原始值
除此之外,该表使用键的散列(而不是值)来查找正确的bucket
除此之外,你对这门课的理解是正确的
但是,我不相信您可以从公共API查看冲突,因为这很可能是在类中处理的。如果您阅读了,您会注意到put()
方法定义如下
put(对象键、对象值)
将指定的值与此映射中的指定键相关联
使用同一个键调用put()
两次时,它将覆盖与该键关联的原始值
除此之外,该表使用键的散列(而不是值)来查找正确的bucket
除此之外,你对这门课的理解是正确的
但是,我不相信您可以从公共API查看冲突,因为这很可能是在类内部处理的。下面是使用HashMap的更新代码。我还更改了equals()方法以包含count字段,但将其从hashCode()方法中删除。这将成功创建冲突,如果使用调试器查看HashMap,您可以看到它在发生冲突的bucket中构建的列表:
public class HashMapTest {
public static void main(String[] args) {
HashMapTest test = new HashMapTest();
test.execute();
}
public void execute() {
HashMap<Node, Node> nodeMap = new HashMap<Node, Node>();
Node node1 = new Node("data1", 1);
Node node2 = new Node("data2", 2);
Node node3 = new Node("data1", 2);
Node node4 = new Node("data1", 1);
System.out.println("node1 hash: " + node1.hashCode());
System.out.println("node2 hash: " + node2.hashCode());
System.out.println("node3 hash: " + node3.hashCode());
System.out.println("node1 hash == node2 hash? " + (node1.hashCode() == node2.hashCode() ? "true" : "false"));
System.out.println("node2 hash == node3 hash? " + (node2.hashCode() == node3.hashCode() ? "true" : "false"));
System.out.println("node1 hash == node3 hash? " + (node1.hashCode() == node3.hashCode() ? "true" : "false"));
System.out.println("node1.equals(node2)? " + (node1.equals(node2) ? "true" : "false"));
System.out.println("node2.equals(node3)? " + (node2.equals(node3) ? "true" : "false"));
System.out.println("node1.equals(node3)? " + (node1.equals(node3) ? "true" : "false"));
System.out.println("");
nodeMap.put(node1, node1);
System.out.println("added node1 to hash map");
System.out.println("hash map size: " + nodeMap.size());
System.out.println("hash map entry set size: " + nodeMap.entrySet().size());
System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false"));
System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false"));
System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false"));
System.out.println("node1's count from map: " + nodeMap.get(node1).getCount());
System.out.println("");
nodeMap.put(node2, node2);
System.out.println("added node2 to hash map");
System.out.println("hash map size: " + nodeMap.size());
System.out.println("hash map entry set size: " + nodeMap.entrySet().size());
System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false"));
System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false"));
System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false"));
System.out.println("node1's count from map: " + nodeMap.get(node1).getCount());
System.out.println("");
// note that if node4 is used then it replaces the value that stored node1
nodeMap.put(node3, node3);
System.out.println("added node3 to hash map");
System.out.println("hash map size: " + nodeMap.size());
System.out.println("hash map entry set size: " + nodeMap.entrySet().size());
System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false"));
System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false"));
System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false"));
System.out.println("node1's count from map: " + nodeMap.get(node1).getCount());
}
protected class Node {
private String data;
private Integer count;
public Node(String data, Integer count) {
this.data = data;
this.count = count;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((data == null) ? 0 : data.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (count == null) {
if (other.count != null)
return false;
}
else
if (!count.equals(other.count))
return false;
if (data == null) {
if (other.data != null)
return false;
}
else
if (!data.equals(other.data))
return false;
return true;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
private HashMapTest getOuterType() {
return HashMapTest.this;
}
}
下面是使用HashMap的更新代码。我还更改了equals()方法以包含count字段,但将其从hashCode()方法中删除。这将成功创建冲突,如果使用调试器查看HashMap,您可以看到它在发生冲突的bucket中构建的列表:
public class HashMapTest {
public static void main(String[] args) {
HashMapTest test = new HashMapTest();
test.execute();
}
public void execute() {
HashMap<Node, Node> nodeMap = new HashMap<Node, Node>();
Node node1 = new Node("data1", 1);
Node node2 = new Node("data2", 2);
Node node3 = new Node("data1", 2);
Node node4 = new Node("data1", 1);
System.out.println("node1 hash: " + node1.hashCode());
System.out.println("node2 hash: " + node2.hashCode());
System.out.println("node3 hash: " + node3.hashCode());
System.out.println("node1 hash == node2 hash? " + (node1.hashCode() == node2.hashCode() ? "true" : "false"));
System.out.println("node2 hash == node3 hash? " + (node2.hashCode() == node3.hashCode() ? "true" : "false"));
System.out.println("node1 hash == node3 hash? " + (node1.hashCode() == node3.hashCode() ? "true" : "false"));
System.out.println("node1.equals(node2)? " + (node1.equals(node2) ? "true" : "false"));
System.out.println("node2.equals(node3)? " + (node2.equals(node3) ? "true" : "false"));
System.out.println("node1.equals(node3)? " + (node1.equals(node3) ? "true" : "false"));
System.out.println("");
nodeMap.put(node1, node1);
System.out.println("added node1 to hash map");
System.out.println("hash map size: " + nodeMap.size());
System.out.println("hash map entry set size: " + nodeMap.entrySet().size());
System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false"));
System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false"));
System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false"));
System.out.println("node1's count from map: " + nodeMap.get(node1).getCount());
System.out.println("");
nodeMap.put(node2, node2);
System.out.println("added node2 to hash map");
System.out.println("hash map size: " + nodeMap.size());
System.out.println("hash map entry set size: " + nodeMap.entrySet().size());
System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false"));
System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false"));
System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false"));
System.out.println("node1's count from map: " + nodeMap.get(node1).getCount());
System.out.println("");
// note that if node4 is used then it replaces the value that stored node1
nodeMap.put(node3, node3);
System.out.println("added node3 to hash map");
System.out.println("hash map size: " + nodeMap.size());
System.out.println("hash map entry set size: " + nodeMap.entrySet().size());
System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false"));
System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false"));
System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false"));
System.out.println("node1's count from map: " + nodeMap.get(node1).getCount());
}
protected class Node {
private String data;
private Integer count;
public Node(String data, Integer count) {
this.data = data;
this.count = count;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((data == null) ? 0 : data.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (count == null) {
if (other.count != null)
return false;
}
else
if (!count.equals(other.count))
return false;
if (data == null) {
if (other.data != null)
return false;
}
else
if (!data.equals(other.data))
return false;
return true;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
private HashMapTest getOuterType() {
return HashMapTest.this;
}
}
好吧,这是有道理的。我可以修改它以使用HashMap并更改hashCode()和equals()方法以获得冲突,我看到它在键的hashCode()映射到的bucket中构建列表。但是,我注意到,如果传递给put(K,V)的键等于另一个键,那么它会覆盖该值。我认为它只是使用hashCode()来标识bucket,然后使用equal()来表示其中的值。显然,如果key equal()是另一个键,那么它将替换关联的值。一旦我超过8小时的限制来回答我的问题,我将发布代码来突出这一区别。它使用hashCode()
来标识bucket,并使用键上的equal()
方法。在成功检索值之前,映射不知道与键关联的值是什么,因此无法对该值使用equal()
方法。HashMap
的要点是键与值的1:1映射,如果一个键映射到多个值,那么它就不是一个非常有效的映射,因为不可能检索所有值!好吧,这是有道理的。我可以修改它以使用HashMap并更改hashCode()和equals()方法以获得冲突,我看到它在键的hashCode()映射到的bucket中构建列表。但是,我注意到,如果传递给put(K,V)的键等于另一个键,那么它会覆盖该值。我认为它只是使用hashCode()来标识bucket,然后使用equal()来表示其中的值。显然,如果key equal()是另一个键,那么它将替换关联的值。一旦我超过8小时的限制来回答我的问题,我将发布代码来突出这一区别。它使用hashCode()
来标识bucket,并使用键上的equal()
方法。在成功检索值之前,映射不知道与键关联的值是什么,因此无法对该值使用equal()
方法。HashMap
的要点是键与值的1:1映射,如果一个键映射到多个值,那么它就不是一个非常有效的映射,因为不可能检索所有值!顺便说一下,您可以简化hashCode
方法以返回数据=无效的data.hashCode():0
不需要先加1,然后再乘以31。顺便说一下,您可以简化hashCode
方法以返回数据=无效的data.hashCode():0代码>不需要先加1再乘以31。
public class HashMapTest {
public static void main(String[] args) {
HashMapTest test = new HashMapTest();
test.execute();
}
public void execute() {
HashMap<Node, Node> nodeMap = new HashMap<Node, Node>();
Node node1 = new Node("data1", 1);
Node node2 = new Node("data2", 2);
Node node3 = new Node("data1", 2);
Node node4 = new Node("data1", 1);
System.out.println("node1 hash: " + node1.hashCode());
System.out.println("node2 hash: " + node2.hashCode());
System.out.println("node3 hash: " + node3.hashCode());
System.out.println("node1 hash == node2 hash? " + (node1.hashCode() == node2.hashCode() ? "true" : "false"));
System.out.println("node2 hash == node3 hash? " + (node2.hashCode() == node3.hashCode() ? "true" : "false"));
System.out.println("node1 hash == node3 hash? " + (node1.hashCode() == node3.hashCode() ? "true" : "false"));
System.out.println("node1.equals(node2)? " + (node1.equals(node2) ? "true" : "false"));
System.out.println("node2.equals(node3)? " + (node2.equals(node3) ? "true" : "false"));
System.out.println("node1.equals(node3)? " + (node1.equals(node3) ? "true" : "false"));
System.out.println("");
nodeMap.put(node1, node1);
System.out.println("added node1 to hash map");
System.out.println("hash map size: " + nodeMap.size());
System.out.println("hash map entry set size: " + nodeMap.entrySet().size());
System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false"));
System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false"));
System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false"));
System.out.println("node1's count from map: " + nodeMap.get(node1).getCount());
System.out.println("");
nodeMap.put(node2, node2);
System.out.println("added node2 to hash map");
System.out.println("hash map size: " + nodeMap.size());
System.out.println("hash map entry set size: " + nodeMap.entrySet().size());
System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false"));
System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false"));
System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false"));
System.out.println("node1's count from map: " + nodeMap.get(node1).getCount());
System.out.println("");
// note that if node4 is used then it replaces the value that stored node1
nodeMap.put(node3, node3);
System.out.println("added node3 to hash map");
System.out.println("hash map size: " + nodeMap.size());
System.out.println("hash map entry set size: " + nodeMap.entrySet().size());
System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false"));
System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false"));
System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false"));
System.out.println("node1's count from map: " + nodeMap.get(node1).getCount());
}
protected class Node {
private String data;
private Integer count;
public Node(String data, Integer count) {
this.data = data;
this.count = count;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((data == null) ? 0 : data.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (count == null) {
if (other.count != null)
return false;
}
else
if (!count.equals(other.count))
return false;
if (data == null) {
if (other.data != null)
return false;
}
else
if (!data.equals(other.data))
return false;
return true;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
private HashMapTest getOuterType() {
return HashMapTest.this;
}
}
node1 hash: 1077170390
node2 hash: 1077170391
node3 hash: 1077170390
node1 hash == node2 hash? false
node2 hash == node3 hash? false
node1 hash == node3 hash? true
node1.equals(node2)? false
node2.equals(node3)? false
node1.equals(node3)? false
added node1 to hash map
hash map size: 1
hash map entry set size: 1
hash map contains node1? true
hash map contains node2? false
hash map contains node3? false
node1's count from map: 1
added node2 to hash map
hash map size: 2
hash map entry set size: 2
hash map contains node1? true
hash map contains node2? true
hash map contains node3? false
node1's count from map: 1
added node3 to hash map
hash map size: 3
hash map entry set size: 3
hash map contains node1? true
hash map contains node2? true
hash map contains node3? true
node1's count from map: 1