日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HashSet源码分析

發布時間:2025/4/16 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HashSet源码分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

HashSet底層是HashMap實現的,關于HashMap的分析請移步到HashMap源碼分析

屬性

//底層使用HashMap來實現 private transient HashMap<E,Object> map;//虛擬的Object對象作為HashMap的value private static final Object PRESENT = new Object();

HashSet底層是使用HashMap實現的,由于HashMap存儲的是<Key,Value>鍵值對,而HashSet不需要Value,所以HashSet內部使用了一個虛擬的Object對象作為底層HashMap的值。

構造方法

public HashSet() {//底層會初始化一個空的HashMap,并使用默認初始容量為16和加載因子0.75。map = new HashMap<>();}public HashSet(Collection<? extends E> c) {map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));addAll(c);}public HashSet(int initialCapacity, float loadFactor) {map = new HashMap<>(initialCapacity, loadFactor);}public HashSet(int initialCapacity) {map = new HashMap<>(initialCapacity);}HashSet(int initialCapacity, float loadFactor, boolean dummy) {map = new LinkedHashMap<>(initialCapacity, loadFactor);}

初始化HashSet時,可以指定初始化容量和負載因子。因為HashSet是由HashMap來實現,如果不指定,則默認值都與HashMap中的一樣,即默認初始化容量為16,默認負載因子為0.75。

add方法

public boolean add(E e) {return map.put(e, PRESENT)==null; }//HashMap的put方法 public V put(K key, V value) { //map為空表時,進行擴充 if (table == EMPTY_TABLE) { inflateTable(threshold); } //如果key為null,直接定位到table[0]處,進行處理 if (key == null) return putForNullKey(value); //計算key的hash值 int hash = hash(key); //根據key的hash,定位key在table中索引 int i = indexFor(hash, table.length); //判斷key是否存在 for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; //如果key已存在,則覆蓋原value //【判斷key相等】:也就是判斷兩個Object是否相等 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { //暫存舊值V oldValue = e.value; //用新值覆蓋舊值e.value = value; e.recordAccess(this); //返回舊值(方法返回后,可能還要用到舊值) return oldValue; } }//key不存在 //修改次數+1 modCount++; //添加<k,v> addEntry(hash, key, value, i); return null; }

從源碼可以看出,HashSet如果添加了重復的元素,即key已存在時,會進行覆蓋操作。 借助該特點,可以使用HashSet實現去重操作。

?

面試題:
1.HashSet的實現原理?

2.Set中元素是無序的

HashSet set=new HashSet(); set.add("a"); set.add("b"); set.add("c"); set.add("d"); System.out.println(set);//結果:[d,b,c,a]

3.HashSet不允許重復

情景0

//兩次添加"a" HashSet set=new HashSet(); System.out.println(set.add("a"));//結果:true set.add("b"); set.add("c"); set.add("d"); System.out.println(set.add("a"));//結果:false

情景1

//兩次分別添加不同的對象。 HashSet set=new HashSet();System.out.println(set.add(new People("張三")));//true System.out.println(set.add(new People("張三")));//true

情景2

//兩次都是添加p1 HashSet set=new HashSet();People p1=new People("張三"); System.out.println(set.add(p1));//true System.out.println(set.add(p1));//false

情景3

//兩次分別添加s1,s2(顯然,s1和s2是不同的對象)。 HashSet set=new HashSet();String s1=new String("a"); String s2=new String("a");System.out.println(set.add(s1));//true System.out.println(set.add(s2));//false

4.HashSet如何保證不重復的?

hashset底層用的hashmap實現,hashset實際上是沒有value的,只是用了一個虛擬的value(Object PRESENT),每個key的值都是該value。

當要插入一個存在的對象時,hashmap對相同的key則進行value值覆蓋操作,所以相當于用新的<key,PRESENT>覆蓋掉舊的<key,PRESENT>。所以表面看起來沒有插入新的重復元素,也就保證了不重復。

5.HashSet添加元素的過程

①HashCode
當HashSet在添加元素時,會先調用hashCode()方法,判斷即將加入的元素的hashCode是否與集合中的元素有相同的,如果沒有,則允許添加該元素。如果有相同的,則繼續調用equals()方法,如果equals()方法返回true,則表示對象已經加入過了,不允許再添加了。否則,如果equels方法返回false,則允許添加新元素。
②equals

對于兩個對象來說,如果使用equals返回true, 則這兩個對象的hashcode一定相同。
對于兩個對象來說,如果使用equals返回false,則這兩個對象的hashcode不一定不相同(可以相同或者不同)。如果不同,可以提高性能。

對于Object類來說,不同的Object對象的hashcode值是不同的(hashCode值表示對象的地址)

String類的hashCode()方法重寫了Object類的hashCode()方法,只要兩個String對象的內容相同則認為hashCode相同,所以情景3比較特殊。

轉載于:https://www.cnblogs.com/rouqinglangzi/p/10291706.html

總結

以上是生活随笔為你收集整理的HashSet源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。