Java中hashset底層實現機制
阿新 • • 發佈:2019-01-07
今天寫演算法,遇到了這個問題:
HashSet的底層是用hashmap實現的,用到了物件的equals方法和hashcode值例如,當要add一個新物件時,先計算他的hashcode值,根據hashcode值,插入到hashmap合適的位置中,如果位置上有元素,則採用equals方法比較,如果相同不插入,如果不相同,新找一個位置插入如果位置上沒有元素,則直接插入。因此,當插入新元素時,如果這個元素和已存中的某一個元素(any)的hashcode相同且equals()返回為真,那麼就不能插入備註:除非你重寫了equals方法, 否則,equals為真的兩元素,其hashcode也一定相同那麼我遇到的問題也好解決了:第一種情況,兩個都是Int陣列,arr1和arr2的hashcode就不相同,arr2找到的hashmap中的位置與arr1就不相同,不需要用equals方法,arr2就可以插入.第二種情況,兩個是arraylist,arr2的hashcode和arr1的hashcode相同,有興趣的同學可以去看一下AbstactList.java中HashCode()方法,到底是怎麼計算arraylist的hashcode值,這裡我貼出來
HashSet<int[]> hs = new HashSet<>();
int[] arr1 = {4,5};
int[] arr2 = {4,5};
hs.add(arr1);
hs.add(arr2);
System.out.println(hs.size());
結果為:2輸出為:1原因:HashSet<ArrayList<Integer>> hs = new HashSet<>(); ArrayList<Integer> arr1 = new ArrayList<>(){{add(4);add(5)}}; ArrayList<Integer> arr2 = new ArrayList<>(){{add(4);add(5)}}; hs.add(arr1); hs.add(arr2); System.out.prinln(hs.size());
HashSet的底層是用hashmap實現的,用到了物件的equals方法和hashcode值例如,當要add一個新物件時,先計算他的hashcode值,根據hashcode值,插入到hashmap合適的位置中,如果位置上有元素,則採用equals方法比較,如果相同不插入,如果不相同,新找一個位置插入如果位置上沒有元素,則直接插入。因此,當插入新元素時,如果這個元素和已存中的某一個元素(any)的hashcode相同且equals()返回為真,那麼就不能插入備註:除非你重寫了equals方法, 否則,equals為真的兩元素,其hashcode也一定相同那麼我遇到的問題也好解決了:第一種情況,兩個都是Int陣列,arr1和arr2的hashcode就不相同,arr2找到的hashmap中的位置與arr1就不相同,不需要用equals方法,arr2就可以插入.第二種情況,兩個是arraylist,arr2的hashcode和arr1的hashcode相同,有興趣的同學可以去看一下AbstactList.java中HashCode()方法,到底是怎麼計算arraylist的hashcode值,這裡我貼出來
因為hashcode值相同,則找到了相同的位置,於是使用equals()方法,arraylist的equals方法如下:public int hashCode() { int hashCode = 1; for (E e : this) hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); return hashCode; }
對每一個元素呼叫其equals方法,都為true就返回為真,所以這一看一下Integer的equal()public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof List)) return false; ListIterator<E> e1 = listIterator(); ListIterator<?> e2 = ((List<?>) o).listIterator(); while (e1.hasNext() && e2.hasNext()) { E o1 = e1.next(); Object o2 = e2.next(); if (!(o1==null ? o2==null : o1.equals(o2))) return false; } return !(e1.hasNext() || e2.hasNext()); }
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Integer的equals方法,值相同則返回為真,所以arr2和arr1中依次迴圈比較,每個值得equals都返回為真,則arr2.equals(arr1)返回真,所以就不能插入