类信息
- 属于hashmap的子类
- 内部的存储单元多了 before 、after
- 带有指向头部和尾部的指针
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
{
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
private static final long serialVersionUID = 3801124242820219131L;
transient LinkedHashMap.Entry<K,V> head;
transient LinkedHashMap.Entry<K,V> tail;
final boolean accessOrder;
}
内部存储单元
可以和hashmap进行对比, 只是多了 before、after
/**
* HashMap.Node subclass for normal LinkedHashMap entries.
*/
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
构造函数
- LinkedHashMap(int initialCapacity, loat loadFactor, boolean accessOrder)
- accessOrder 参数为 true的话, 每次在get元素的时候, 会把这个元素移动到最后面的位置
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
public LinkedHashMap() {
super();
accessOrder = false;
}
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
afterNodeAccess(Node<K,V> e)
- 在 accessOrder 为真 并且当前元素不是最后一个的情况下, 开始移动
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;
}
}
添加元素
本身是hashmap的子类, 在其内部维护着指向尾部元素和首部元素的指针, 并且其内部存储单元相比hashmap多了 after 和 before 两个属性用来维护元素之间的添加顺序, 在添加元素的时候,使用的是hashmap的 添加方法, 但是在新建节点的时候会使用after 和 before维护一下添加元素之间的顺序
- linkedhashmap是有序的
- 维护插入时候的顺序
- 在添加元素的时候维护插入元素的顺序
- 有新建节点和新建树节点两种
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
LinkedHashMap.Entry<K,V> p =
new LinkedHashMap.Entry<K,V>(hash, key, value, e);
linkNodeLast(p);
return p;
}
TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next);
linkNodeLast(p);
return p;
}
// link at the end of list
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}
得到元素
- 根据构造linkedhashmap时候的初始化方法, 可以在得到元素的时候, 把当前元素的顺序置为尾部元素
public V get(Object key) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
删除元素
- 再删除元素之后, 取消维护他的顺序链接
void afterNodeRemoval(Node<K,V> e) { // unlink
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.before = p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a == null)
tail = b;
else
a.before = b;
}
和 hashmap 在遍历元素时候对比
hashmap
- 无序, i 是添加元素时候计算出来的hash值
public final void forEach(Consumer<? super K> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next)
action.accept(e.key);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
linkedhashmap
- 有序, 使用head 和 after指针进行遍历
public final void forEach(Consumer<? super K> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
action.accept(e.key);
if (modCount != mc)
throw new ConcurrentModificationException();
}
总结
- 有序
- 可以维护添加元素的顺序
- 使用head afer指针 维护
- 线程不安全
- hashmap的子类, 并未做出线程安全的处理
- get 的时候如果当前元素不是尾部元素, 会自动调整为尾部元素