您好,登錄后才能下訂單哦!
這篇文章主要介紹“JDK的LinkedHashMap怎么使用”,在日常操作中,相信很多人在JDK的LinkedHashMap怎么使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”JDK的LinkedHashMap怎么使用”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
package org.corey.demo;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
Map map = new LinkedHashMap(4);
map.put("1", "corey");
map.put("2", "syna");
map.put("3", "bobo");
Iterator it=map.keySet().iterator();
System.out.println("-------------------------linked hash map----------------------");
while(it.hasNext()){
String key=(String)it.next();
System.out.println(key+":"+map.get(key));
}
Map map2 = new HashMap(4);
map2.put("1", "corey");
map2.put("2", "syna");
map2.put("3", "bobo");
Iterator it2=map2.keySet().iterator();
System.out.println("-------------------------hash map----------------------");
while(it2.hasNext()){
String key=(String)it2.next();
System.out.println(key+":"+map2.get(key));
}
}
}
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)原理;
private transient Entry<K,V> header;
在LinkedHashMap中含有一個(gè)Entry的屬性;注意,這個(gè)Entry不是上一次我們在HashMap中見到的單向Entry,他被擴(kuò)充了:
private static class Entry<K,V> extends HashMap.Entry<K,V> {
//他有兩個(gè)指針分別指向了before和after的Entry
//請(qǐng)注意,不要把next和他們混淆了,next的用處還是和HashMap中一//樣;
Entry<K,V> before, after;
Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
super(hash, key, value, next);
}
private void remove() {
before.after = after;
after.before = before;
}
、
//在當(dāng)前節(jié)點(diǎn)前面插入節(jié)點(diǎn);
private void addBefore(Entry<K,V> existingEntry) {
after = existingEntry;
before = existingEntry.before;
before.after = this;
after.before = this;
}
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
if (lm.accessOrder) {
lm.modCount++;
remove();
addBefore(lm.header);
}
}
void recordRemoval(HashMap<K,V> m) {
remove();
}
}
因?yàn)長inkedHashMap是繼承的HashMap,那么他們的增刪改的操作基本一致,只是利用了模板模式具有了不同的實(shí)現(xiàn);
我們來看一下put方法吧;
下面是HashMap的put方法:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
void addEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
if (size++ >= threshold)
resize(2 * table.length);
}
在上一節(jié)中我們已經(jīng)詳細(xì)的分析過了,在LinkedHashMap中被重載的方法是addEntry;
void addEntry(int hash, K key, V value, int bucketIndex) {
createEntry(hash, key, value, bucketIndex);
Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) {
removeEntryForKey(eldest.key);
} else {
if (size >= threshold)
resize(2 * table.length);
}
}
void createEntry(int hash, K key, V value, int bucketIndex) {
//和以前一樣,首先操作了table序列的鏈表枝條;
HashMap.Entry<K,V> old = table[bucketIndex];
Entry<K,V> e = new Entry<K,V>(hash, key, value, old);
table[bucketIndex] = e;
//關(guān)鍵在于這一步做了什么;我們知道他在header之前插入了Entry;
e.addBefore(header);
size++;
}
Header元素在構(gòu)造的時(shí)候被初始化,記得嗎,這個(gè)方法是HashMap在構(gòu)造函數(shù)中利用模板模式傳下來的
void init() {
header = new Entry<K,V>(-1, null, null, null);
header.before = header.after = header;
}
開始的時(shí)候Header頭尾都是指向自身的;
第二步的時(shí)候就是被e.addBefore(header);
private void addBefore(Entry<K,V> existingEntry) {
after = existingEntry;
before = existingEntry.before;
before.after = this;
after.before = this;
}
如果再put那么就是:
我們再來看一看他的keySet是如何得到的:
重載了newKeyIterator() 的方法:
Iterator<K> newKeyIterator() { return new KeyIterator(); }
我們看一下迭代器是如何實(shí)現(xiàn)的:
private abstract class LinkedHashIterator<T> implements Iterator<T> {
//從開始的圖3我們可見,第一次加入的節(jié)點(diǎn)是位于header.after的位置;
Entry<K,V> nextEntry = header.after;
Entry<K,V> lastReturned = null;
int expectedModCount = modCount;
//nextnEntry不是header就不是末尾
public boolean hasNext() {
return nextEntry != header;
}
public void remove() {
if (lastReturned == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
LinkedHashMap.this.remove(lastReturned.key);
lastReturned = null;
expectedModCount = modCount;
}
Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (nextEntry == header)
throw new NoSuchElementException();
//指針沿著after往下走
Entry<K,V> e = lastReturned = nextEntry;
//預(yù)先把nextEntry移動(dòng)到了下一位
nextEntry = e.after;
return e;
}
}
把next方法抽象出去是因?yàn)関alues和keySet的迭代次序是一樣的,就是返回的數(shù)值不同,所以可以把
Entry的遍歷方式推到上層,而values和keys分別留給子類實(shí)現(xiàn);
private class KeyIterator extends LinkedHashIterator<K> {
public K next() { return nextEntry().getKey(); }
}
private class KeyIterator extends LinkedHashIterator<K> {
public K next() { return nextEntry().getKey(); }
}
private class ValueIterator extends LinkedHashIterator<V> {
public V next() { return nextEntry().value; }
}
private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() { return nextEntry(); }
}
到此,關(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í)用的文章!
免責(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)容。