天天看点

LinkedHashMap与LinkedHashSet

LinkedHashMap

LinkedHashmap将hash表与链表结合起来,它实现了Map接口,它与hashmap不同的是它内部还持有一个双向链表,并且这个双向链表决定了内部的键值对的迭代顺序。通常情况下该顺序就是键值对被插入hash表的顺序,当hash表执行覆盖操作的时候,是不会影响他原来的顺序的,它通常可以用来产生一个与原来的hash表具有相同顺序的拷贝hash表,不管原先的hash表是什么实现。

通过特定的构造方法,可以将LinkedHashMap中的键值对的顺序指定为其最后被访问的顺序,因此这种方式构造的hash表是比较适合做LRU缓存的。LinkedHashMap像hashmap一样也是可以允许放入空的键和空的值的。

LinkedHashMap不是线程安全的,因此多个线程并发的访问同一实例的时候会存在线程安全问题。

LinkedHashMap继承自HashMap,并实现了Map接口。

containsValue方法

get方法

getOrDefault方法

clear方法

forEach方法

replaceAllf方法

LinkedHashSet

LinkedHashSet内部使用双向链表保存元素与元素之间的顺序,元素与元素之间的顺序可以是元素的插入顺序,如果是按照插入顺序的话,那么当元素重新插入的时候并不会收到影响,其也允许放入空的元素,LinkedHashSet也不是线程安全的,多个线程并发的访问的时候需要在外部施加一定的同步机制。

LinkedHashSet继承自HashSet,同时实现了Set接口,使得它具有Set接口所声明的一切方法的api,同时使用极少的代码就可以完成给定的功能。

LinkedHashSet是如何实现链表功能的呢,其实其构造方法是关键,可以看到起所有的构造方法都是调用的父类也就是HashSet的构造方法,而该构造方法可以再看一下

内部其实是创建了一个LinkedHashMap,所以LinkedHashSet的相应功能是通过底层的LinkedHashMap实现的。

可以发现LinkedHashMap通过继承自HashMap因此具有了HashMap的所有的能力,但是因为LinkedHashMap需要保存一定的顺序规则,它是通过继承HashMap的Node结点并通过改动Node结点使其具有了双向链表的特性,从而在不怎么改变原有实现的情况下,将内部的Entry(在HashMap中是Node)以双端链表的形式连接了起来(所以整个LinkedHashMap的关键就是Entry内部的before和after)。同时在对内部的Entry进行迭代器的遍历的时候,是遍历内部的双端队列的链表(否则大费周章搞这个链表干啥)。这样带来的一个额外的优点就是当hashmap的初始容量开的很大的时候,防止大部分的桶是空的或者很稀疏,遍历带来的低效的问题。

继续阅读