Java中的Map是一種非常常見的數據結構,其具有鍵值對的形式存儲,通常用來存儲一組相關的數據。而put方法是Map接口中的一種方法,該方法用來將一組鍵值對存儲到Map中。在本篇文章中,我們將從多個方面介紹Java中put方法的使用。
一、put方法的基本使用
首先,我們來看一下put方法的基本使用:
Map<String, String> map = new HashMap<>();
map.put("name", "Tom");
map.put("age", "18");
上述代碼中,我們首先定義了一個Map實例,然後使用put方法將兩組鍵值對存儲到Map中。在這裡,我們傳入的是一個String類型的鍵和一個String類型的值。需要注意的是,在使用put方法的時候,如果Map中已經存在了這個鍵,則會用新的值替換舊的值。
二、put方法的返回值
除了將一組鍵值對存儲到Map中之外,put方法還可以返回該鍵對應的舊值。例如:
Map<String, String> map = new HashMap<>();
map.put("name", "Tom");
String oldValue = map.put("name", "Jerry");
System.out.println(oldValue); // 輸出Tom
上述代碼中,我們首先使用put方法將鍵為”name”、值為”Tom”的鍵值對存儲到Map中。接着,我們再次使用put方法,將鍵為”name”、值為”Jerry”的鍵值對存儲到Map中。注意到在此過程中,Map中名為”name”的鍵已經存在,因此使用新的值”Jerry”替換掉了舊值”Tom”。而此時,put方法返回的值就是被替換掉的舊值”Tom”。
三、put方法的默認實現
Map接口中提供了多個不同的實現類,如HashMap、TreeMap、ConcurrentHashMap等。而在這些實現類中,put方法的具體實現也是不同的。下面我們來詳細介紹一下HashMap和TreeMap中put方法的默認實現。
1. HashMap中put方法的默認實現
HashMap是一種散列表,它採用了”拉鏈法”來解決哈希衝突。下面是HashMap中put方法的默認實現:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
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 {
// 省略其他代碼段
}
modCount++; // 記錄Map中實際存儲的鍵值對數量
if (++size >= threshold) // 如果Map中的鍵值對數量超過了擴容閾值
resize(); // 則進行擴容
afterNodeInsertion(evict);
return null;
}
上述代碼中,我們可以看到put方法的具體實現其實是調用了putVal方法,這個方法就是HashMap中put方法的具體實現。在這個方法中,我們可以看到,首先通過hash方法計算出了當前鍵對應的哈希值。接着,如果鍵對應的槽位沒有被佔用,就直接在該槽位中存儲該鍵值對。否則,就需要對已經存在的鍵值對進行更新操作。最後,如果Map中的鍵值對數量超過了擴容閾值,就需要進行擴容操作。
2. TreeMap中put方法的默認實現
TreeMap是一種基於紅黑樹的映射。下面是TreeMap中put方法的默認實現:
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp; Entry<K,V> parent;
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
上述代碼中,我們可以看到put方法的具體實現是直接在TreeMap中新建一個Entry實例,並將其插入到紅黑樹中。在實現中,首先通過比較器(如果存在)或者鍵實現Comparable接口的compareTo方法(如果鍵沒有指定比較器並且實現了Comparable接口)來判斷當前鍵應該插入到紅黑樹的哪個位置。接着,如果節點已經存在,則用新的值替換舊的值,否則就將新節點插入到紅黑樹中。最後,如果擺動操作遵循紅黑樹插入的規則。
四、put方法的使用技巧
做到了上述的put方法的基本使用、返回值、默認實現,接下來我們將介紹一些使用技巧。
1. 使用putIfAbsent方法避免鍵的重複插入
在實際開發中,有時候需要向Map中插入一組鍵值對,但是如果鍵已經存在,則不插入。這個需求可以通過putIfAbsent方法來實現。例如:
Map<String, String> map = new HashMap<>();
map.put("name", "Tom");
map.putIfAbsent("name", "Jerry");
System.out.println(map.get("name")); // 輸出Tom
上述代碼中,由於”Tom”已經被存儲為”name”鍵的值,因此使用putIfAbsent方法插入”Jerry”時會失敗,不會對Map做出任何修改。在輸出時,我們可以發現”name”鍵的值仍然為”Tom”。
2. 使用putAll方法批量插入鍵值對
如果需要將一個Map中的所有鍵值對都插入到另一個Map中,那麼可以使用putAll方法。例如:
Map<String, String> map1 = new HashMap<>();
map1.put("name", "Tom");
map1.put("age", "18");
Map<String, String> map2 = new HashMap<>();
map2.putAll(map1);
System.out.println(map2.get("name")); // 輸出Tom
System.out.println(map2.get("age")); // 輸出18
上述代碼中,我們首先定義了map1,並向其中插入了兩組鍵值對。接着,我們定義了一個空的map2,使用putAll方法將map1中的所有鍵值對都插入到map2中。最後,我們通過get方法檢驗了一下map2中存儲的鍵值對是否正確。
3. 使用computeIfAbsent方法避免重複計算
在實際開發中,有時候需要根據鍵的值來計算一些數據,並將計算結果存儲到Map中。如果鍵的值已經對應了一個存儲的計算結果,那麼就可以直接獲取這個結果而不需要重複計算。這個需求可以使用computeIfAbsent方法來實現。例如:
Map<String, Integer> map = new HashMap<>();
map.put("count", 1);
Integer result = map.computeIfAbsent("count", key -> computeCount(key));
System.out.println(result); // 輸出1
上述代碼中,我們首先定義了一個名為count的鍵,對應的值為1。接着,我們使用computeIfAbsent方法來獲取該鍵對應的計算結果。在這裡,computeIfAbsent方法會首先檢查名為count的鍵是否存在。由於count鍵已經被存儲在map中,因此computeIfAbsent方法不會對該鍵進行計算,而是直接返回其對應的值1。最後,我們通過輸出檢查一下返回值是否為1。
五、小結
本文主要介紹了Java中Map接口中的put方法。我們從put方法的基本使用、返回值、默認實現和使用技巧四個方面進行了詳細的介紹。除此之外,還結合具體的代碼實現,幫助讀者更加深入地了解Java中put方法的使用。
原創文章,作者:SJSQ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/140078.html
微信掃一掃
支付寶掃一掃