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-hk/n/140078.html