HashSet的add的實現原理深入刨析[jdk8]
例項
程式碼
Set<String> set = Sets.newHashSet();
boolean flag1 = set.add("111");
boolean flag2 = set.add("222");
boolean flag3 = set.add("333");
boolean flag4 = set.add("222");
boolean flag5 = set.add("555");
執行跟蹤
可以發現在add 第二個“222”時,返回了false;未重複時,返回true
原理分析
step1:進入HashSet.java類
#HashSet.java
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
......省略無關程式碼
public boolean add(E e) {
return map.put(e, PRESENT)==null;#通過map.put方法返回值是否為null來確定
}
step2:進入HashMap類
#HashMap.java
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {#hash並不等同hashCode方法,而是根據hashCode計算出來的,二者結果線性相關
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); #key的hashcode異或其無符號右移16位
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))#這是程式碼裡判斷的語句,可以看出,這裡用hash和equals都比較了,需要兩個都返回true才可以
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
其中Node程式碼如下
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
如果我們沒有實現hashCode或者equals,二者都會呼叫Object上的方法,Object上hashCode方法是一個本地方法,返回的值應該是物件在記憶體中地址,而equals方法內是通過==判斷地址是否一致.
#Object.java
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
所以,這一問的結論就有了,hashCode和equals方法都會用來判斷相等,根據hashCode計算出的hash相等(這和直接要求hashCode相等有些區別),而且equals返回true時,才斷定二者相等.相關文章
- HashSet淺析原理學習
- 說一下HashSet的實現原理?
- 基於React 原始碼深入淺出setState:深度刨析updater的結構和原理React原始碼
- RocketMQ 4.2.0 broker JVM優化引數深入刨析MQJVM優化
- 深入理解ReentrantLock的實現原理ReentrantLock
- Kubernetes(k8s)底層網路原理刨析K8S
- C# 委託原理刨析,外加和事件對比C#事件
- 深入 Go 的 Map 使用和實現原理Go
- HashSet 實現類
- Java ArrayList.add 的實現Java
- 深入理解Vue的computed實現原理及其實現方式Vue
- 深入理解Vue的watch實現原理及其實現方式Vue
- 併發——深入分析ThreadLocal的實現原理thread
- 深入理解 Taier:MR on Yarn 的實現原理AIYarn
- Java面試題 從原始碼角度分析HashSet實現原理?Java面試題原始碼
- iOS應用程式的脫殼實現原理淺析iOS
- 淺析Spring中AOP的實現原理——動態代理Spring
- Java集合 HashSet的原理及常用方法Java
- 深入淺出 Java 中列舉的實現原理Java
- Flutter動畫實現原理淺析Flutter動畫
- 深入解析 ResNet:實現與原理
- add(1)(2)(3)...函式的實現函式
- 深入學習MySQL事務:ACID特性的實現原理MySql
- 深入解析 PyTorch 的 BatchNorm2d:原理與實現PyTorchBATORM
- Laravel 核心--深入剖析 Laravel 框架 Jwt 元件的實現原理Laravel框架JWT元件
- GFS分散式檔案系統、結合實驗分析各種儲存卷的特點。深入刨析分散式儲存的方式。分散式
- 前端動畫實現以及原理淺析前端動畫
- 深入原始碼解析 tapable 實現原理原始碼
- [深入探索] VueJS Scoped CSS 實現原理VueJSCSS
- 深入理解Java中的底層阻塞原理及實現Java
- 深入理解多執行緒(一)——Synchronized的實現原理執行緒synchronized
- 【GoLang 那點事】深入 Go 的 Map 使用和實現原理Golang
- 深入理解Java的垃圾回收機制(GC)實現原理JavaGC
- 【死磕Java併發】-----深入分析synchronized的實現原理Javasynchronized
- 【死磕Java併發】—–深入分析volatile的實現原理Java
- Angular 依賴注入機制實現原理的深入介紹Angular依賴注入
- 看不懂的資料結構-連結串列深度刨析資料結構
- HashMap底層實現原理/HashMap與HashTable區別/HashMap與HashSet區別HashMap