(original) (raw)
m) { + public void recordAccess(HashMap<k,v> m) { } /** * This method is invoked whenever the entry is * removed from the table. */ - void recordRemoval(HashMap<k,v> m) { + public void recordRemoval(HashMap<k,v> m) { } } @@ -1680,6 +1680,19 @@ return new HashMap.Entry<>(hash, key, value, next); } + /** + * Factory method to create new TreeNode entry instead of existing entry. + */ + TreeNode<k, v=""> newTreeNode(HashMap.Entry<k,v> entry, Object next, TreeNode parent) { + return new TreeNode<>(entry.hash, entry.key, entry.value, next, parent); + } + + /** + * Factory method to create new TreeNode entry. + */ + TreeNode<k, v=""> newTreeNode(int hash, K key, V value, Object next, TreeNode parent) { + return new TreeNode<>(hash, key, value, next, parent); + } private abstract class HashIterator implements Iterator { Object next; // next entry to return, an Entry or a TreeNode Index: jdk/src/share/classes/java/util/LinkedHashMap.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- jdk/src/share/classes/java/util/LinkedHashMap.java (date 1369341286000) +++ jdk/src/share/classes/java/util/LinkedHashMap.java (date 1369563382000) @@ -24,7 +24,6 @@ */ package java.util; -import java.io.*; /** *
Hash table and linked list implementation of the Map interface, @@ -238,8 +237,9 @@ */ @Override void init() { - header = new Entry<>(-1, null, null, null); - header.before = header.after = header; + header = new EntryImpl<>(-1, null, null, null); + header.setBefore(header); + header.setAfter(header); } /** @@ -253,12 +253,12 @@ public boolean containsValue(Object value) { // Overridden to take advantage of faster iterator if (value==null) { - for (Entry e = header.after; e != header; e = e.after) - if (e.value==null) + for (Entry e = header.getAfter(); e != header; e = e.getAfter()) + if (e.getValue()==null) return true; } else { - for (Entry e = header.after; e != header; e = e.after) - if (value.equals(e.value)) + for (Entry e = header.getAfter(); e != header; e = e.getAfter()) + if (value.equals(e.getValue())) return true; } return false; @@ -284,7 +284,7 @@ if (e == null) return null; e.recordAccess(this); - return e.value; + return e.getValue(); } /** @@ -293,36 +293,71 @@ */ public void clear() { super.clear(); - header.before = header.after = header; + header.setBefore(header); + header.setAfter(header); } /** - * LinkedHashMap entry. + * LinkedHashMap entry interface. */ - private static class Entry<k,v> extends HashMap.Entry<k,v> { + private interface Entry<k, v=""> extends Map.Entry<k, v=""> { + + Entry<k, v=""> getBefore(); + void setBefore(Entry<k, v=""> before); + + Entry<k, v=""> getAfter(); + void setAfter(Entry<k, v=""> after); + + void remove(); + void addBefore(Entry<k,v> existingEntry); + + void recordAccess(HashMap<k,v> m); + void recordRemoval(HashMap<k,v> m); + } + + /** + * LinkedHashMap entry simple implementation. + */ + private static final class EntryImpl<k,v> extends HashMap.Entry<k,v> implements Entry<k, v=""> { // These fields comprise the doubly linked list used for iteration. - Entry<k,v> before, after; + private Entry<k,v> before, after; - Entry(int hash, K key, V value, Object next) { + EntryImpl(int hash, K key, V value, Object next) { super(hash, key, value, next); } + public Entry<k, v=""> getBefore() { + return before; + } + + public void setBefore(Entry<k, v=""> before) { + this.before = before; + } + + public Entry<k, v=""> getAfter() { + return after; + } + + public void setAfter(Entry<k, v=""> after) { + this.after = after; + } + /** * Removes this entry from the linked list. */ - private void remove() { - before.after = after; - after.before = before; + public void remove() { + before.setAfter(after); + after.setBefore(before); } /** * Inserts this entry before the specified existing entry in the list. */ - private void addBefore(Entry<k,v> existingEntry) { + public void addBefore(Entry<k,v> existingEntry) { after = existingEntry; - before = existingEntry.before; - before.after = this; - after.before = this; + before = existingEntry.getBefore(); + before.setAfter(this); + after.setBefore(this); } /** @@ -331,7 +366,7 @@ * If the enclosing Map is access-ordered, it moves the entry * to the end of the list; otherwise, it does nothing. */ - void recordAccess(HashMap<k,v> m) { + public void recordAccess(HashMap<k,v> m) { LinkedHashMap<k,v> lm = (LinkedHashMap<k,v>)m; if (lm.accessOrder) { lm.modCount++; @@ -340,13 +375,78 @@ } } - void recordRemoval(HashMap<k,v> m) { + public void recordRemoval(HashMap<k,v> m) { remove(); } - } - + } + + /** + * LinkedHashMap entry and TreeNode implementation. + */ + private static final class LinkedTreeNode<k,v> extends TreeNode<k,v> implements Entry<k, v=""> { + // These fields comprise the doubly linked list used for iteration. + private Entry<k,v> before, after; + + LinkedTreeNode(int hash, K key, V value, Object next, TreeNode parent) { + super(hash, key, value, next, parent); + } + + public Entry<k, v=""> getBefore() { + return before; + } + + public void setBefore(Entry<k, v=""> before) { + this.before = before; + } + + public Entry<k, v=""> getAfter() { + return after; + } + + public void setAfter(Entry<k, v=""> after) { + this.after = after; + } + + /** + * Removes this entry from the linked list. + */ + public void remove() { + before.setAfter(after); + after.setBefore(before); + } + + /** + * Inserts this entry before the specified existing entry in the list. + */ + public void addBefore(Entry<k,v> existingEntry) { + after = existingEntry; + before = existingEntry.getBefore(); + before.setAfter(this); + after.setBefore(this); + } + + /** + * This method is invoked by the superclass whenever the value + * of a pre-existing entry is read by Map.get or modified by Map.put. + * If the enclosing Map is access-ordered, it moves the entry + * to the end of the list; otherwise, it does nothing. + */ + public void recordAccess(HashMap<k,v> m) { + LinkedHashMap<k,v> lm = (LinkedHashMap<k,v>)m; + if (lm.accessOrder) { + lm.modCount++; + remove(); + addBefore(lm.header); + } + } + + public void recordRemoval(HashMap<k,v> m) { + remove(); + } + } + private abstract class LinkedHashIterator implements Iterator { - Entry<k,v> nextEntry = header.after; + Entry<k,v> nextEntry = header.getAfter(); Entry<k,v> lastReturned = null; /** @@ -366,7 +466,7 @@ if (modCount != expectedModCount) throw new ConcurrentModificationException(); - LinkedHashMap.this.remove(lastReturned.key); + LinkedHashMap.this.remove(lastReturned.getKey()); lastReturned = null; expectedModCount = modCount; } @@ -378,7 +478,7 @@ throw new NoSuchElementException(); Entry<k,v> e = lastReturned = nextEntry; - nextEntry = e.after; + nextEntry = e.getAfter(); return e; } } @@ -388,7 +488,7 @@ } private class ValueIterator extends LinkedHashIterator { - public V next() { return nextEntry().value; } + public V next() { return nextEntry().getValue(); } } private class EntryIterator extends LinkedHashIterator<map.entry<k,v>> { @@ -410,9 +510,9 @@ super.addEntry(hash, key, value, bucketIndex, checkIfNeedTree); // Remove eldest entry if instructed - Entry<k,v> eldest = header.after; + Entry<k,v> eldest = header.getAfter(); if (removeEldestEntry(eldest)) { - removeEntryForKey(eldest.key); + removeEntryForKey(eldest.getKey()); } } @@ -421,11 +521,35 @@ */ @Override HashMap.Entry<k,v> newEntry(int hash, K key, V value, Object next) { - Entry<k,v> newEntry = new Entry<>(hash, key, value, next); + EntryImpl<k,v> newEntry = new EntryImpl<>(hash, key, value, next); newEntry.addBefore(header); return newEntry; + } + + /* + * Create a new LinkedTreeNode entry instead of existing LinkedHashMap.Entry and + * relink it into before/after list instead of existing entry + */ + @Override + TreeNode<k, v=""> newTreeNode(HashMap.Entry<k, v=""> entry, Object next, TreeNode parent) { + LinkedTreeNode<k, v=""> newTreeNode = new LinkedTreeNode<>(entry.hash, entry.key, entry.value, next, parent); + LinkedHashMap.Entry<k, v=""> linkedEntry = (LinkedHashMap.Entry<k, v="">) entry; + LinkedHashMap.Entry<k, v=""> after = linkedEntry.getAfter(); + linkedEntry.remove(); + newTreeNode.addBefore(after); + return newTreeNode; + } + + /* + * Create a new LinkedTreeNode and setup the before/after pointers + */ + @Override + TreeNode<k, v=""> newTreeNode(int hash, K key, V value, Object next, TreeNode parent) { + LinkedTreeNode<k, v=""> newTreeNode = new LinkedTreeNode<>(hash, key, value, next, parent); + newTreeNode.addBefore(header); + return newTreeNode; } - + /** * Returns true if this map should remove its eldest entry. * This method is invoked by put and putAll after Index: jdk/src/share/classes/java/util/TreeBin.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- jdk/src/share/classes/java/util/TreeBin.java (date 1369341286000) +++ jdk/src/share/classes/java/util/TreeBin.java (date 1369563382000) @@ -325,9 +325,9 @@ TreeNode f = first; TreeNode x; if (entry != null) { - x = new TreeNode(entry, f, p); + x = map.newTreeNode(entry, f, p); } else { - x = new TreeNode(map.newEntry(h, k, v, null), f, p); + x = map.newTreeNode(h, k, v, f, p); } first = x; Index: jdk/src/share/classes/java/util/TreeNode.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- jdk/src/share/classes/java/util/TreeNode.java (date 1369341286000) +++ jdk/src/share/classes/java/util/TreeNode.java (date 1369563382000) @@ -40,17 +40,16 @@ * * Node type for TreeBin */ -final class TreeNode<k,v> { +class TreeNode<k,v> extends HashMap.Entry<k, v=""> { TreeNode parent; // red-black tree links TreeNode left; TreeNode right; TreeNode prev; // needed to unlink next upon deletion boolean red; - final HashMap.Entry<k,v> entry; + final HashMap.Entry<k,v> entry = this; // TODO: remove field and replace references in code with this - TreeNode(HashMap.Entry<k,v> entry, Object next, TreeNode parent) { - this.entry = entry; - this.entry.next = next; + TreeNode(int hash, K key, V value, Object next, TreeNode parent) { + super(hash, key, value, next); this.parent = parent; } } </k,v></k,v></k,v></k,></k,v></k,v></k,></k,></k,></k,></k,></k,></k,></k,></k,v></k,v></k,v></k,v></k,v></map.entry<k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,></k,></k,></k,></k,v></k,></k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,></k,></k,></k,></k,v></k,v></k,></k,v></k,v></k,v></k,v></k,v></k,></k,></k,></k,></k,></k,></k,v></k,v>
</k,></k,v></k,></k,v></k,v></k,v>