初识LinkedHashMap
上两篇文章讲了HashMap和HashMap在多线程下激发的问题,说明白,HashMap是一种非经常见、很是有用的荟萃,而且在多线程环境下利用不妥会有线程安详问题。
大大都环境下,只要不涉及线程安详问题,Map根基都可以利用HashMap,不外HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap安排的顺序,也就是无序。HashMap的这一缺点往往会带来困扰,因为有些场景,我们等候一个有序的Map。
这个时候,LinkedHashMap就闪亮登场了,它固然增加了时间和空间上的开销,可是通过维护一个运行于所有条目标双向链表,LinkedHashMap担保了元素迭代的顺序。
四个存眷点在LinkedHashMap上的谜底

LinkedHashMap根基数据布局
关于LinkedHashMap,先提两点:
1、LinkedHashMap可以认为是HashMap+LinkedList,即它既利用HashMap操纵数据布局,又利用LinkedList维护插入元素的先后顺序
2、LinkedHashMap的根基实现思想就是—-多态。可以说,领略多态,再去领略LinkedHashMap道剖析事半功倍;反之也是,对付LinkedHashMap道理的进修,也可以促进和加深对付多态的领略。
为什么可以这么说,首先看一下,LinkedHashMap的界说:
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
{
...
}
看到,LinkedHashMap是HashMap的子类,软件开发,自然LinkedHashMap也就担任了HashMap中所有非private的要领。再看一下LinkedHashMap中自己的要领:

看到LinkedHashMap中并没有什么操纵数据布局的要领,也就是说LinkedHashMap操纵数据布局(好比put一个数据),和HashMap操纵数据的要领完全一样,无非就是细节上有一些的差异而已。
LinkedHashMap和HashMap的区别在于它们的根基数据布局上,看一下LinkedHashMap的根基数据布局,也就是Entry:
private static class Entry<K,V> extends HashMap.Entry<K,V> {
// These fields comprise the doubly linked list used for iteration.
Entry<K,V> before, after;
Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
super(hash, key, value, next);
}
...
}
列一下Entry内里有的一些属性吧:
个中前面四个,也就是赤色部门是从HashMap.Entry中担任过来的;后头两个,也就是蓝色部门是LinkedHashMap独占的。不要搞错了next和before、After,next是用于维护HashMap指定table位置上毗连的Entry的顺序的,before、After是用于维护Entry插入的先后顺序的。
照旧用图暗示一下,列一部属性罢了:

初始化LinkedHashMap
如果有这么一段代码:
public static void main(String[] args)
{
LinkedHashMap<String, String> linkedHashMap =
new LinkedHashMap<String, String>();
linkedHashMap.put("111", "111");
linkedHashMap.put("222", "222");
}
首先是第3行~第4行,new一个LinkedHashMap出来,看一下做了什么:
public LinkedHashMap() {
super();
accessOrder = false;
}
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
table = new Entry[DEFAULT_INITIAL_CAPACITY];
init();
}
void init() {
header = new Entry<K,V>(-1, null, null, null);
header.before = header.after = header;
}
/** * The head of the doubly linked list. */ private transient Entry<K,V> header;
这里呈现了第一个多态:init()要领。尽量init()要领界说在HashMap中,可是由于:
1、LinkedHashMap重写了init要领
2、实例化出来的是LinkedHashMap
因此实际挪用的init要领是LinkedHashMap重写的init要领。假设header的地点是0×00000000,那么初始化完毕,实际上是这样的:

LinkedHashMap添加元素