LinkedHashMap继承了HashMap类并实现了Map接口,其内部维护了一个双向链表,在每次插入数据或者修改访问数据,在双链表中会存在相应的增删高的操作,从而实现将无序的HashMap通过双链表将其管理为有序状态的map类型。
内部节点
|
|
LinkedHashMap中的节点Entry继承了HashMap中内部类Node,为其添加两个链表以实现节点之间的有序存储。
|
|
同时存在两个成员变量,head和tail指向双链表的首尾两端,以及一个accessOrder,accessOrder指定双链表的迭代顺序,如果其为true,则采用访问顺序,如果为false,则采用插入顺序。
|
|
构造方法
|
|
新增节点
- LinkedHashMap添加节点采用的是HashMap中的put方法。在putVal方法中调用了newNode()方法。
|
|
- LinkedHashMap重写了构建节点newNode()方法。
|
|
- 每次构建新节点时,通过linkNodeLast(p)将新节点链接在内部双向链表的尾部。
|
|
- putVal方法中最后调用了afterNodeInsertion(evict),很容易发现,在HashMap中这个方法是空的,而LinkedHashMap中重写了这些方法,用于对相应操作之后对双链表的修改。如果是按照
|
|
|
|
- Demo展示:
|
|
|
|
删除节点
- LinkedHashMap没有重写删除节点,调用HashMap中的删除方法。删除之后通过调用重写之后的afterNodeRemoveal()这个回调方法来对双链表进行调整。
|
|
- Demo展示
|
|
|
|
查找节点
- 没错,LinkedHashMap重写了get方法及getOrDefaul方法,比较简单,就是查找,查找完之后,如果迭代顺序采用是访问顺序,则需要调用函数afterNodeAccess来调整双向链表。
|
|
|
|
Demo展示
按照插入顺序输出
123456789101112public class LinkedHashMapDemo {public static void main(String[] args) {Map<Integer,String> map = new LinkedHashMap<>();for (int i = 1; i < 7; i++) {map.put(i, "" + i);}System.out.println(map.toString());map.get(3);map.get(6);System.out.println(map);}}12{1=1, 2=2, 3=3, 4=4, 5=5, 6=6}{1=1, 2=2, 3=3, 4=4, 5=5, 6=6}按照访问顺序输出,accessOrder=true
12345678910111213public class LinkedHashMapDemo {public static void main(String[] args) {Map<Integer,String> orderMap = new LinkedHashMap<Integer, String >(16,0.75f, true);for (int i = 1; i < 7; i++) {orderMap.put(i, "" + i);}System.out.println(orderMap.toString());orderMap.get(3);System.out.println(orderMap);orderMap.get(1);System.out.println(orderMap);}}123{1=1, 2=2, 3=3, 4=4, 5=5, 6=6}{1=1, 2=2, 4=4, 5=5, 6=6, 3=3}{2=2, 4=4, 5=5, 6=6, 3=3, 1=1}
containsValue方法
HashMap中的containsValue方法:
|
|
LinkedHashMap中:
|
|
显然,后者的实现更加的高效。
遍历
LinkedHashMap中重写了entrySet()方法:
|
|
- 重写之后迭代LinkedHashMap就是从内部维护的双链表的表头开始循环输出。
总结
- LinkedHashMap继承HashMap,只需要重写几个方法,来改变其迭代遍历的顺序。同时在插入数据,访问数据,修改数据,会增加双链表上的节点或者调整顺序,来决定迭代时的输出顺序。
- 相应操作的回调函数,HashMap中有相应的空方法,也就意味着LinkedHashMap只需要重写这几个回调函数,而不用重写插入和删除方法。
- LinkedhashMap重写了get方法。
- LinkedHashMap优化了containsValue方法,提高其遍历性能。
测试代码