java static關鍵字,java hashset 實現_HashSet實現原理分析(Java源碼剖析)

 2023-10-20 阅读 23 评论 0

摘要:本文將深入討論HashSet實現原理的源碼細節。在分析源碼之前,首先我們需要對HashSet有一個基本的理解。HashSet只存儲不同的值,set中是不會出現重復值的。HashSet和HashMap一樣也需要實現hash算法來計算對象的hash值,但不同的是,HashMap中添加一個

本文將深入討論HashSet實現原理的源碼細節。在分析源碼之前,首先我們需要對HashSet有一個基本的理解。

HashSet只存儲不同的值,set中是不會出現重復值的。

HashSet和HashMap一樣也需要實現hash算法來計算對象的hash值,但不同的是,HashMap中添加一個鍵值對的時候, (Key, Value),hash函數計算的是Key的hash值。而HashSet則是計算value的hash值。當我們調用HashSet的add(E e)的方法 的時候,我們會計算機元素e的hash值,如果這個值之前沒出現過,就說明這個元素在set中不存在,如果出現過,就說明。set中已經存在了,就添加失敗。

java static關鍵字、知道了上述的基本概念之后,我們就可以打開JDK源碼,來一探究竟了。

關于hashSet的實現原理,最重要的一個點就是HashSet內部是使用HashMap來存儲對象的。所以請讀者務必先對hashMap的實現原理有一個初步的認識。參考筆者的文章HashMap實現原理分析(Java源碼剖析)

我們可以看到HashSet有多個構造函數,但每個構造函數都是初始化了一個HashMap的對象

/**

linkedhashset原理?* Constructs a new, empty set; the backing HashMap instance has

* default initial capacity (16) and load factor (0.75).

*/

public HashSet() {

java.util、map = new HashMap<>();

}

/**

* Constructs a new set containing the elements in the specified

java 多線程編程、* collection. The HashMap is created with default load factor

* (0.75) and an initial capacity sufficient to contain the elements in

* the specified collection.

*

java hash函數。* @param c the collection whose elements are to be placed into this set

* @throws NullPointerException if the specified collection is null

*/

public HashSet(Collection extends E> c) {

java arraylist,map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));

addAll(c);

}

/**

javahashset原理?* Constructs a new, empty set; the backing HashMap instance has

* the specified initial capacity and the specified load factor.

*

* @param initialCapacity the initial capacity of the hash map

Java hashset、* @param loadFactor the load factor of the hash map

* @throws IllegalArgumentException if the initial capacity is less

* than zero, or if the load factor is nonpositive

*/

hashset方法?public HashSet(int initialCapacity, float loadFactor) {

map = new HashMap<>(initialCapacity, loadFactor);

}

/**

* Constructs a new, empty set; the backing HashMap instance has

* the specified initial capacity and default load factor (0.75).

*

* @param initialCapacity the initial capacity of the hash table

* @throws IllegalArgumentException if the initial capacity is less

* than zero

*/

public HashSet(int initialCapacity) {

map = new HashMap<>(initialCapacity);

}

我們可以觀察到,默認的構造函數指定的初始化容量是16,負載因子是0.75.。也就是說創建了一個長度為16的數組,默認的負載因子為0.75,當達到容量時,map會自動擴容。

而這里的HashMap的是如下:

private transient HashMap map;

可以看到,HashSet中使用的HashMap,key為Set的元素類型,value為Object。

add(E e)

我們來看add方法的實現

/**

* Adds the specified element to this set if it is not already present.

* More formally, adds the specified element e to this set if

* this set contains no element e2 such that

* (e==null???e2==null?:?e.equals(e2)).

* If this set already contains the element, the call leaves the set

* unchanged and returns false.

*

* @param e element to be added to this set

* @return true if this set did not already contain the specified

* element

*/

public boolean add(E e) {

return map.put(e, PRESENT)==null;

}

PRESENT的定義

// Dummy value to associate with an Object in the backing Map

private static final Object PRESENT = new Object();

我們看到PRESENT是一個靜態的類對象,Object類型。所有HashSet的實例都共享這個對象。

也就是說,我們在向set中添加一個e元素的時候,實際上就是在像map添加一個(e, Object)的鍵值對。我們添加的元素e變成了map中的key,而value則都是Obeject對象。又因為map中key值是唯一的,而value是可以重復的。所以我們添加的e作為key的話,就可以保證添加成功的話,e一定是唯一的。這就實現了set的唯一性。

remove(Object o)

我們接下來看remove的代碼

/**

* Removes the specified element from this set if it is present.

* More formally, removes an element e such that

* (o==null???e==null?:?o.equals(e)),

* if this set contains such an element. Returns true if

* this set contained the element (or equivalently, if this set

* changed as a result of the call). (This set will not contain the

* element once the call returns.)

*

* @param o object to be removed from this set, if present

* @return true if the set contained the specified element

*/

public boolean remove(Object o) {

return map.remove(o)==PRESENT;

}

我們知道Hashmap中移除一個key的話,會返回這個key值鎖對應的value,而我們這里的map,所有的key的value都是同一個對象PRESENT,所以我們這里只需要判斷map.remove(o)的返回值是不是PRESENT,就可以確定是否成功移除了

iterator()

我們知道hashSet沒有get方法,想要獲取HashSet的元素需要調用iterator()

為什么會這樣呢?

其實只要我們結合HashSet底層是由HashMap實現的就知道,我們添加的元素值都被map當成了key來存儲,顯然沒有從map中獲取單獨一個key的方法,但是我們可以獲取所有key,調用keySet方法即可。

/**

* Returns an iterator over the elements in this set. The elements

* are returned in no particular order.

*

* @return an Iterator over the elements in this set

* @see ConcurrentModificationException

*/

public Iterator iterator() {

return map.keySet().iterator();

}

小結

HashSet由于內部實現是完全基于HashMap的,所以原理較為簡單,代碼也不多,源碼加上注釋也就是300多行。

關于hashSet的實現原理,我們需要掌握一下幾點

hashSet內部用HashMap來存儲元素

HashSet利用本身的值來計算hash值,因為值被當作hashmap的key,而hashmap是利用key來計算hash值的

因為hashset將value當作key來存儲,所以根據map的key值唯一的原理,我們就可以實現set的無重復元素的功能

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/150974.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息