hashset,hashset 学习心得

package equals.tran; import java.util.HashSet; import java.util.Set; public class Example { public static void main(String[] args) { Point p = new Point(1, 2); Set set = new HashSet(); set.add(p); System.out.println(set.contains(new Point(1, 2))); p.setX(2); System.out.println(set.contains(new Point(1, 2))); System.out.println(set.contains(new Point(2, 2))); for (Point temp : set) { if (temp.equals(p)) { System.out.println("OK, temp.equals(p)"); System.out.println("temp.x = " + temp.getX() +", temp.y = " + temp.getY()); } } } } class Point { private int x; private int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Point other = (Point) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } }
答案是
true false false OK, temp.equals(p) temp.x = 2, temp.y = 2
为什么第2个和第3个事false呢
因为hashset其实底层是HashMap实现的
private transient HashMap map;
hashset的contains方法其实调用了hashMap的containsKey方法,containsKey方法通过getEntry方法查找对象
final Entry getEntry(Object key) { int hash = (key == null) ? 0 : hash(key.hashCode()); for (Entry e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } return null; }
我们可以看到,首先会根据key对象的hashcode方法生成hash值,再通过hash方法生成一个hash值(h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4);这不是很理解),因为我们知道hashMap是通过数组加链表实现的,所以首先通过生成的hash值为索引在数组里面查找位置,在用equals方法判断是否相当,如果不相等,则next继续,找到以后先判断两个对象的hash值是否相等,再判断两个对象是否=或者equals,两个条件是与关系,。
我们再来看例子,首先存进去一个Point(1,2)对象,它的hash值为994,根据hash函数确定在数组的位置(hash函数一般为余上数组的长度),执行
set.contains(new Point(1, 2))
通过1,2算出hash值还是994,找到数组的位子,然后比较,当然是相等的,返回true
然后更改p的y值
p.setX(2);
注意,这里虽然更改了p的y值,但他再hashset里的位子还是没有变化
然后执行
set.contains(new Point(1, 2))
通过1,2算出hash值994,查找到数组的位子,这里是找到了对象的,然后判断hash值是否相等,这里找到的对象的hash值是1025,994!=1025,所以返回false
set.contains(new Point(2, 2))
通过x=2,y=2算出hash值1025,然后查找数组位子上,但这里是找不到对象的,所以返回false
我也纠结了很久,看了源代码,这就是我的理解,有错的地方欢迎指正!
Tags:  学习心得 hashset

延伸阅读

最新评论

发表评论