In diesem Artikel wird hauptsächlich der LinkedHashMap-Quellcode in Java analysiert, der einen bestimmten Referenzwert hat.
Übersicht:
LinkedHashMap-Implementierung Map erbt HashMap , basierend auf der Hashtabellen- und Kettenlistenimplementierung von Map, mit vorhersehbarer Iterationsreihenfolge.
LinedHashMap verwaltet eine doppelt verknüpfte Listenstruktur, die für alle Einträge gilt. Die verknüpfte Liste definiert die Iterationsreihenfolge, die Einfüge- oder Zugriffsreihenfolge sein kann.
Das Knotenobjekt von LintHashMap erbt das Knotenobjekt von HashMap und fügt Vorher- und Nachher-Zeiger hinzu:
/** * LinkedHashMap节点对象 */ static class Entry<K,V> extends HashMap.Node<K,V> { Entry<K,V> before, after; Entry(int hash, K key, V value, Node<K,V> next) { super(hash, key, value, next); } }
lintHashMap-Initialisierung:
accessOrder wird, einfach ausgedrückt, verwendet, um die Reihenfolge der Elemente zu steuern.
accessOrder ist wahr: Es bedeutet, dass es in der Reihenfolge des Zugriffs gespeichert wird, das heißt, wer zuerst darauf zugreift, wird zuerst eingestuft accessOrder ist falsch, was bedeutet, dass es in der Reihenfolge des Zugriffs gespeichert wird. Die Reihenfolge ist die Reihenfolge, in der Sie die Elemente platzieren.
public LinkedHashMap(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); accessOrder = false; } /** * 生成一个空的LinkedHashMap,并指定其容量大小,负载因子使用默认的0.75, * accessOrder为false表示按照存放顺序来,就是你put元素的时候的顺序 * accessOrder为true: 表示按照访问的顺序来,也就是谁最先访问,就排在第一位 */ public LinkedHashMap(int initialCapacity) { super(initialCapacity); accessOrder = false; } /** * 生成一个空的HashMap,容量大小使用默认值16,负载因子使用默认值0.75 * 默认将accessOrder设为false,按插入顺序排序. */ public LinkedHashMap() { super(); accessOrder = false; } /** * 根据指定的map生成一个新的HashMap,负载因子使用默认值,初始容量大小为Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,DEFAULT_INITIAL_CAPACITY) * 默认将accessOrder设为false,按插入顺序排序. */ public LinkedHashMap(Map<? extends K, ? extends V> m) { super(); accessOrder = false; putMapEntries(m, false); } /** * 生成一个空的LinkedHashMap,并指定其容量大小和负载因子, * 默认将accessOrder设为true,按访问顺序排序 */ public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; }
/** * Implements Map.putAll and Map constructor * * @param m the map * @param evict false when initially constructing this map, else * true (relayed to method afterNodeInsertion). */ final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) { int s = m.size(); if (s > 0) { if (table == null) { // pre-size float ft = ((float)s / loadFactor) + 1.0F; int t = ((ft < (float)MAXIMUM_CAPACITY) ? (int)ft : MAXIMUM_CAPACITY); if (t > threshold) threshold = tableSizeFor(t); } else if (s > threshold) resize(); for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) { K key = e.getKey(); V value = e.getValue(); putVal(hash(key), key, value, false, evict); } } }
Speicher:
Die von put aufgerufene Put-Methode von HashMap ruft zwei leere Methoden auf, die von LinkedHashMap implementiert werden
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 { Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) 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; }
void afterNodeAccess(Node<K,V> p) { } void afterNodeInsertion(boolean evict) { }
void afterNodeAccess(Node<K,V> e) { LinkedHashMap.Entry<K,V> last; // 若访问顺序为true,且访问的对象不是尾结点 if (accessOrder && (last = tail) != e) { // 向下转型,记录p的前后结点 LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; // p的后结点为空 p.after = null; // 如果p的前结点为空 if (b == null) // a为头结点 head = a; else // p的前结点不为空 // b的后结点为a b.after = a; // p的后结点不为空 if (a != null) // a的前结点为b a.before = b; else // p的后结点为空 // 后结点为最后一个结点 last = b; // 若最后一个结点为空 if (last == null) // 头结点为p head = p; else { // p链入最后一个结点后面 p.before = last; last.after = p; } // 尾结点为p tail = p; // 增加结构性修改数量 ++modCount; } }
void afterNodeInsertion(boolean evict) { // possibly remove eldest LinkedHashMap.Entry<K,V> first; //头结点不为空,删除头结点 if (evict && (first = head) != null && removeEldestEntry(first)) { K key = first.key; removeNode(hash(key), key, null, false, true); } }
void afterNodeRemoval(Node<K,V> e) { // unlink LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; p.before = p.after = null; if (b == null) head = a; else b.after = a; if (a == null) tail = b; else a.before = b; }
public V get(Object key) { Node<K,V> e; if ((e = getNode(hash(key), key)) == null) return null; if (accessOrder) afterNodeAccess(e); return e.value; }
void afterNodeAccess(Node<K,V> e) { LinkedHashMap.Entry<K,V> last; // 若访问顺序为true,且访问的对象不是尾结点 if (accessOrder && (last = tail) != e) { // 向下转型,记录p的前后结点 LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; // p的后结点为空 p.after = null; // 如果p的前结点为空 if (b == null) // a为头结点 head = a; else // p的前结点不为空 // b的后结点为a b.after = a; // p的后结点不为空 if (a != null) // a的前结点为b a.before = b; else // p的后结点为空 // 后结点为最后一个结点 last = b; // 若最后一个结点为空 if (last == null) // 头结点为p head = p; else { // p链入最后一个结点后面 p.before = last; last.after = p; } // 尾结点为p tail = p; // 增加结构性修改数量 ++modCount; } }
LinkedValueIterator erbt von LinkedHashIterator, implementiert die Iterator-Schnittstelle, iteriert den Wert in LinkedHashMap
LinkedEntryIterator erbt von LinkedHashIterator, implementiert die Iterator-Schnittstelle und iteriert die Knoten in LinkedHashMap
Das obige ist der detaillierte Inhalt vonBeispiel für das Parsen des LinkedHashMap-Quellcodes in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!