简介Hash
HashCode是一个Int型的值,其所代表的是给对应元素分配的内存地址。
用数组的概念来理解hash算法,数组(是所有能储存一组元素最快的数据结构)。数组的每个元素都有他的索引(下标),我们如果想要访问数组指定的元素,只需要提供其相对应的索引即可。而HashCode便是HashSet的”索引“,通过索引我们便可以快速的定位、访问该元素——这也是Hash算法的价值所在:速度。
HashSet集合判断俩个元素相等的标准是俩个对象通过equals()方法比较相等,并且俩个对象返回的hashCode也相等。
关于HashCode的返回值,下图便于理解:
理解HashCode和equals之间的区别,请分析下列代码:
class A{ int count; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + count; return result; } @Override public String toString() { return "A [count=" + count + "]"; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; A other = (A) obj; if (count != other.count) return false; return true; } public A(int count) { super(); this.count = count; } } public class HashSetDemo { public static void main(String[] args) { HashSet hs = new HashSet(); hs.add(new A(5)); hs.add(new A(-3)); hs.add(new A(9)); hs.add(new A(-2)); System.out.println(hs); Iterator t = hs.iterator(); //取出第一个元素 A first = (A) t.next(); //改变第一个元素的count值 System.out.println(first); System.out.println(t.next()); first.count=-3; System.out.println(hs); hs.remove(first); System.out.println(hs); System.out.println("hs是否包含count为-3的A对象?"+hs.contains(new A(-3))); System.out.println("hs是否包含count为5的A对象?"+hs.contains(new A(5))); } }
运行结果:
原因:
在重写的hashcode方法里面,我们可以看出来hashcode返回值直接跟count挂钩,我们也可以直接写成return count,也行。
result = prime * result + count; //Source自动生成,参数count return result;
理解为,count不同hashcode不同。
从改变的第一个结果: [A [count=-3], A [count=9], A [count=-3], A [count=-2]] 我们可以看出来明显有俩个重复的-3,这是因为我们修改了HashSet里元素的结果。
从改变的第二个结果: [A [count=-3], A [count=9], A [count=-2]] 试图删除count=-3的对象时,HashSet会计算出该对象的Hash值,再进行equals比较。而满足该条件的只有初始化为-3的第三个元素。实际上第一个元素的位置依旧为-2元素的位置,故不满足。这里也解释了,为什么同一内容(equals返回treu),而hash值不同,俩个元素依旧可以添加成功。解释如下图:
图片出处: https://blog.csdn.net/lijiecao0226/article/details/24609559
参考文献:疯狂JAVA