链接的Hashmap经常代表Hashmap (理解Hashmap ),从Hashmap继承,继承Hashmap的80%功能,剩下的20%功能用于排序。
1,LinkedHashMap也使用table存储元素,但元素不再从Node类的Entry类继承,而从Node类的Entry类继承。 添加了两个属性: before和after,它们表示前一个和后一个元素。
staticclassEntryK,VextendsHashMap.NodeK,V{EntryK,Vbefore,after; 输入(int hash、Kkey、Vvalue、NodeK、Vnext ) ) super ) hash、key、value、next ); }
2 )同时为链接的hashmap类添加了三个属性
/**thehead(eldest ) ofthedoublylinkedlist.*/transientlinkedhashmap.entryk,Vhead; /**thetail(youngest ) ofthedoublylinkedlist.*/transientlinkedhashmap.entryk,Vtail;/* * theiterationorderingmethodforthislinkedhashmap : TT true/TT * for access-order,TT false/ttforinsertion-order 2.1 表示最初加入的元素。
2.2 tail的末尾表示最后放入的元素。
2.3访问顺序是否使用访问排序。 最后访问的要素被配置在末尾。 false按插入顺序排序。
3,put时使用父类HashMap的put方法,重写了在put方法中调用的newNode方法。
//HashMapNodeK,vnewnode(inthash,Kkey,Vvalue,NodeK,Vnext ) { return new node } hash,key,value,next; }//LinkedHashMapNodeK,vnewnode(inthash,Kkey,Vvalue,NodeK,Ve ) {LinkedHashMap.EntryK,VP=newlinkedhashmap 返回; (差异1 )实例化的Node调用实例化的Entry(entry继承自Node ),在entry类构造函数中调用super ) hash、key、value、next (散列、密钥) 请注意,它是调用,不是继承。 构造函数不能继承。 此时,未使用Entry添加的before、after这两个参数。
差异2 :入口构造函数调整了一种方法linkNodeLast。
4,链路节点最后
//linkattheendoflistprivatevoidlinknodelast ({ linkedhashmap.entryk,Vp ) linked hashmap.entryk,Vlast=tail; tail=p; if(last==null ) head=p; else{p.before=last; last.after=p; }页脚为空时,将新元素同时作为页眉和页脚。
如果页脚不为空,则将新元素作为页脚链接到原始页脚。
head用于需要删除最旧的元素,tail记录最近添加的元素或最近访问的元素,具体取决于访问顺序。
在此,使用了Entry新添加的before、after两个参数。
5,在上面的例子中,链接的hashmap增加了三个参数,但是现在只使用了head和tail两个,还有一个a
ccessOrder未使用。看下构造函数。 public LinkedHashMap() { super(); accessOrder = false; } public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; }第一个无参构造函数,调用hashmap的无参构造函数,并给final变量accessOrder赋值false。此时LinkedHashMap是一个插入顺序排序的hash表。
第二个构造函数给final变量accessOrder赋值自定义boolean参数。
默认使用插入排序,可使用第二个构造函数实现访问排序。
6,还记得hashmap中putval方法调用的空实现afterNodeAccess方法吗,LinkedHashMap具体实现了。
void afterNodeAccess(Node<K,V> e) { // move node to last LinkedHashMap.Entry<K,V> last; if (accessOrder && (last = tail) != e) { LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; p.after = null; if (b == null) head = a; else b.after = a; if (a != null) a.before = b; else last = b; if (last == null) head = p; else { p.before = last; last.after = p; } tail = p; ++modCount; } }有注释为:// move node to last
如果accessOrder为true,则把传入的元素放到表尾。现实访问排序。
访问排序是在插入排序的基础上实现的。先new entry()插入排序,完了再put时根据accessOrder视情况实现访问排序。
7,另一个空实现的方法afterNodeInsertion也实现了。
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); } } protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { return false; }注释为可能移除最老的元素,但由于条件中调用的removeEldestEntry方法一直返回false,所以不会移除。
总结:LinkedHashMap使用entry新增的两个参数来维护元素之间的关系。
更多java基础类库