溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JDK的LinkedHashMap怎么使用

發(fā)布時(shí)間:2021-12-31 16:02:11 來源:億速云 閱讀:119 作者:iii 欄目:編程語言

這篇文章主要介紹“JDK的LinkedHashMap怎么使用”,在日常操作中,相信很多人在JDK的LinkedHashMap怎么使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”JDK的LinkedHashMap怎么使用”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

  1. package org.corey.demo;


  2. import java.util.HashMap;

  3. import java.util.Iterator;

  4. import java.util.LinkedHashMap;

  5. import java.util.Map;


  6. public class Test {


  7.     /**

  8.      * @param args

  9.      */

  10.     public static void main(String[] args) {

  11.         Map map = new LinkedHashMap(4);

  12.         map.put("1""corey");

  13.         map.put("2""syna");

  14.         map.put("3""bobo"); 


  15.         Iterator it=map.keySet().iterator();

  16.         System.out.println("-------------------------linked hash map----------------------");

  17.         while(it.hasNext()){

  18.             String key=(String)it.next();

  19.             System.out.println(key+":"+map.get(key));

  20.         }


  21.         Map map2 = new HashMap(4);

  22.         map2.put("1""corey");

  23.         map2.put("2""syna");

  24.         map2.put("3""bobo"); 


  25.         Iterator it2=map2.keySet().iterator();

  26.         System.out.println("-------------------------hash map----------------------");

  27.         while(it2.hasNext()){

  28.             String key=(String)it2.next();

  29.             System.out.println(key+":"+map2.get(key));

  30.         }


  31.     }


  32. }

console:

-------------------------linked hash map----------------------
1:corey
2:syna
3:bobo
-------------------------hash map----------------------
2:syna
1:corey
3:bobo

從而可見,我們的問題得到了解決;

現(xiàn)在我們從LinkEdHashMap代碼內(nèi)部來詳細(xì)的分析其實(shí)現(xiàn)原理;

  1. private transient Entry<K,V> header;

在LinkedHashMap中含有一個(gè)Entry的屬性;注意,這個(gè)Entry不是上一次我們在HashMap中見到的單向Entry,他被擴(kuò)充了:

  1.   private static class Entry<K,V> extends HashMap.Entry<K,V> {

  2.         //他有兩個(gè)指針分別指向了before和after的Entry

  3.         //請(qǐng)注意,不要把next和他們混淆了,next的用處還是和HashMap中一//樣;

  4.         Entry<K,V> before, after;


  5.     Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {

  6.             super(hash, key, value, next);

  7.         }



  8.         private void remove() {

  9.             before.after = after;

  10.             after.before = before;

  11.         }


  12.      、

  13.         //在當(dāng)前節(jié)點(diǎn)前面插入節(jié)點(diǎn);

  14.         private void addBefore(Entry<K,V> existingEntry) {

  15.             after  = existingEntry;

  16.             before = existingEntry.before;

  17.             before.after = this;

  18.             after.before = this;

  19.         }



  20.         void recordAccess(HashMap<K,V> m) {

  21.             LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;

  22.             if (lm.accessOrder) {

  23.                 lm.modCount++;

  24.                 remove();

  25.                 addBefore(lm.header);

  26.             }

  27.         }


  28.         void recordRemoval(HashMap<K,V> m) {

  29.             remove();

  30.         }

  31.     }

因?yàn)長inkedHashMap是繼承的HashMap,那么他們的增刪改的操作基本一致,只是利用了模板模式具有了不同的實(shí)現(xiàn);
我們來看一下put方法吧;
下面是HashMap的put方法:

  1. public V put(K key, V value) {

  2.         if (key == null)

  3.             return putForNullKey(value);

  4.         int hash = hash(key.hashCode());

  5.         int i = indexFor(hash, table.length);

  6.         for (Entry<K,V> e = table[i]; e != null; e = e.next) {

  7.             Object k;

  8.             if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

  9.                 V oldValue = e.value;

  10.                 e.value = value;

  11.                 e.recordAccess(this);

  12.                 return oldValue;

  13.             }

  14.         }


  15.         modCount++;

  16.         addEntry(hash, key, value, i);

  17.         return null;

  18.     }

  1.  void addEntry(int hash, K key, V value, int bucketIndex) {

  2.     Entry<K,V> e = table[bucketIndex];

  3.         table[bucketIndex] = new Entry<K,V>(hash, key, value, e);

  4.         if (size++ >= threshold)

  5.             resize(2 * table.length);

  6.     }

在上一節(jié)中我們已經(jīng)詳細(xì)的分析過了,在LinkedHashMap中被重載的方法是addEntry;

  1. void addEntry(int hash, K key, V value, int bucketIndex) {

  2.         createEntry(hash, key, value, bucketIndex);



  3.         Entry<K,V> eldest = header.after;

  4.         if (removeEldestEntry(eldest)) {

  5.             removeEntryForKey(eldest.key);

  6.         } else {

  7.             if (size >= threshold)

  8.                 resize(2 * table.length);

  9.         }

  10.     }

  1.     void createEntry(int hash, K key, V value, int bucketIndex) {

  2.         //和以前一樣,首先操作了table序列的鏈表枝條;

  3.         HashMap.Entry<K,V> old = table[bucketIndex];

  4.     Entry<K,V> e = new Entry<K,V>(hash, key, value, old);

  5.         table[bucketIndex] = e;

  6.         //關(guān)鍵在于這一步做了什么;我們知道他在header之前插入了Entry;

  7.         e.addBefore(header);

  8.         size++;

  9.     }

Header元素在構(gòu)造的時(shí)候被初始化,記得嗎,這個(gè)方法是HashMap在構(gòu)造函數(shù)中利用模板模式傳下來的

  1.     void init() {

  2.         header = new Entry<K,V>(-1, nullnullnull);

  3.         header.before = header.after = header;

  4.     }

開始的時(shí)候Header頭尾都是指向自身的;

JDK的LinkedHashMap怎么使用

第二步的時(shí)候就是被e.addBefore(header);

  1.  private void addBefore(Entry<K,V> existingEntry) {

  2.             after  = existingEntry;

  3.             before = existingEntry.before;

  4.             before.after = this;

  5.             after.before = this;

  6.         }

JDK的LinkedHashMap怎么使用
如果再put那么就是:

JDK的LinkedHashMap怎么使用
我們再來看一看他的keySet是如何得到的:

重載了newKeyIterator() 的方法:  

  1. Iterator<K> newKeyIterator()   { return new KeyIterator();   }

我們看一下迭代器是如何實(shí)現(xiàn)的:

  1.  private abstract class LinkedHashIterator<T> implements Iterator<T> {

  2.         //從開始的圖3我們可見,第一次加入的節(jié)點(diǎn)是位于header.after的位置;

  3.     Entry<K,V> nextEntry    = header.after;


  4.     Entry<K,V> lastReturned = null;


  5.     int expectedModCount = modCount;


  6.         //nextnEntry不是header就不是末尾

  7.     public boolean hasNext() {         

  8.             return nextEntry != header;

  9.     }


  10.     public void remove() {

  11.         if (lastReturned == null)

  12.         throw new IllegalStateException();

  13.         if (modCount != expectedModCount)

  14.         throw new ConcurrentModificationException();


  15.             LinkedHashMap.this.remove(lastReturned.key);

  16.             lastReturned = null;

  17.             expectedModCount = modCount;

  18.     }


  19.     Entry<K,V> nextEntry() {

  20.         if (modCount != expectedModCount)

  21.         throw new ConcurrentModificationException();

  22.             if (nextEntry == header)

  23.                 throw new NoSuchElementException();


  24.             //指針沿著after往下走

  25.             Entry<K,V> e = lastReturned = nextEntry;

  26.             //預(yù)先把nextEntry移動(dòng)到了下一位

  27.             nextEntry = e.after;

  28.             return e;

  29.     }

  30.     }


把next方法抽象出去是因?yàn)関alues和keySet的迭代次序是一樣的,就是返回的數(shù)值不同,所以可以把
Entry的遍歷方式推到上層,而values和keys分別留給子類實(shí)現(xiàn);

  1.   private class KeyIterator extends LinkedHashIterator<K> {

  2.     public K next() { return nextEntry().getKey(); }

  3.     }

  4.     private class KeyIterator extends LinkedHashIterator<K> {

  5.     public K next() { return nextEntry().getKey(); }

  6.     }


  7.     private class ValueIterator extends LinkedHashIterator<V> {

  8.     public V next() { return nextEntry().value; }

  9.     }


  10.     private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {

  11.     public Map.Entry<K,V> next() { return nextEntry(); }

  12.     }

到此,關(guān)于“JDK的LinkedHashMap怎么使用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI