LinkedHashMap的特点:
1.LinkedHashMap继承了HashMap ,实现了Clonable ,serialiable(可序列化) , map接口;
public class LinkedHashMap
extends HashMap
implements Map
{
}
2.提供了AccessOrder参数,用来指定LinkedHashMap的排序方式,accessOrder =false -> 插入顺序进行排序 , accessOrder = true -> 访问顺序进行排序。
LinkedHashMap的优势:
相比于HashMap:迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序。而LinkedHashMap,它虽然增加了时间和空间上的开销,通过一个双向链表,LinkedHashMap保证了元素迭代的顺序。该迭代顺序有两种,可以是插入顺序或者是访问顺序。LinkedHashMap继承了HashMap类,有着HashMap的所有功能,还提供了记住元素添加顺序的方法。
LinkedHashMap和HashMap的异同点:
1.linkedHashMap虽然继承HashMap, 但实现了双线链表 ,有固定的顺序,与插入entry的顺序一样; 而HashMap存储的方式是无序的。
2.LinkedHashMap包含removeEldestEntry()方法,而HashMap则没有;
protected boolean removeEldestEntry(Map.Entry eldest) {
return false;
}
key——value键值对:
1.Key和Value都允许空
2.Key重复会覆盖、Value允许重复
安全性:
非线程安全
继承关系:
都实现了Clonable ,serialiable(可序列化) , map接口;
LinkedHashMap底层数据结构:
数组加链表
LinkedHashMap可以认为是HashMap+LinkedList,它可以使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序。
LinkedHashMap成员变量:
// LinkedHashMap维护了一个双向链表,header是链表头,不存储数据。
private transient Entry
// accessOrder(有序性的标志),accessOrder=true(访问有序),默认为false(插入有序)
private final boolean accessOrder;
Entry内部类:
//before:指向前一个entry元素。after:指向后一个entry元素
Entry before, after;
//使用的是父类HashMap的Entry构造
next是用于维护HashMap指定table位置上连接的Entry的顺序的,before、After是用于维护Entry插入的先后顺序的。
Entry(int hash, K key, V value, HashMap.Entry next) {
super(hash, key, value, next);
}
LinkedHashMap并没有重写父类的put()方法,说明调用put方法时实际上调用的是父类的put方法。按照顺序将entry插入到头结点为header的双向链表中;
linkedHashMap的get()方法:判断accessOlder的值 是需要按访问顺序还是遍历顺序来进行操作。
public V get(Object key) {
//1.调用HashMap的getEntry方法得到e
Entry e = (Entry) getEntry(key);
if (e == null){
return null;
}
//2.LinkedHashMap加入的操作
e.recordAccess(this);
return e.value;
}
void recordAccess(HashMap m) {
LinkedHashMap lm = (LinkedHashMap)m;
if (lm.accessOrder) {
lm.modCount++;
remove();
//因为是双向循环链表,所以在头节点之前插入的节点也就是链表的尾节点
addBefore(lm.header);
}
}
private void addBefore(Entry existingEntry) {
after = existingEntry;
before = existingEntry.before;
before.after = this;
after.before = this;
}
LinkedHashMap的remove()方法,是将双线链表的某一个节点移除,而不移除数组加链表上的节点。
private void remove() {
//this.before.after = this.after;
//this.after.before = this.before; 这样看可能会更好理解,this指的就是要删除的那个元素。
before.after = after;
after.before = before;
}
LinkedHashMap的containsValue方法:首先处理value为null的情况, 其次它不像HashMap一样遍历整个数组, 而是通过遍历双线链表header来查找value;
LinkedHashMap可以保存元素的插入顺序,顺序有两种方式一种是按照插入顺序排序,一种按照访问做排序。默认以插入顺序排序,性能比HashMap略低,线程也是不安全的。
一般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果要按顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,用LinkedHashMap 可以实现,它还可以按读取顺序来排列.