1.LinkedHashSet、LinkedHashMap总结
- LinkedHashSet底层实现为LinkedHashMap
- 数据结构为数组+双链表/红黑树(当数组长度不小于64,链表长度不小于8,该链表转成树结构)
- 线程不安全
- 根据插入顺序进行排序
备注:
红黑树(特殊的平衡二叉树)5大特性:
每个节点或者是黑色,或者是红色。
根节点是黑色。
每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
如果一个节点是红色的,则它的子节点必须是黑色的。
从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
2.分点详解
2.1 LinkedHashSet
2.1.1 继承实现情况
2.1.2 构造方法
//1.无参构造方法
public LinkedHashSet() {
/**调用父类HashSet的构造方法,dummy只是为了重载加的参数,没有具体含义
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
**/
//默认初始数组长度16,加载因子为0.75
super(16, .75f, true);
}
//2.有参构造方法,数组长度
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
//3.有参构造方法,数组长度及加载因子
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
2.1.3 添加数据
使用父类HashSet的添加方法。
2.2 LinkedHashMap
2.2.1 继承实现情况
2.2.2 构造方法
调用父类HashMap的构造方法。
//此参数是元素排序,等于true的时候是按哈希值排序,等于false的时候是按插入顺序排序
final boolean accessOrder;
//1.无参构造方法
public LinkedHashMap() {
super();
accessOrder = false;
}
//2.有参构造方法,数组长度
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
//3.有参构造方法,数组长度和加载因子
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
2.2.3 扩容机制
新增元素使用父类HashMap的put方法,(关键点来了)LinkedHashMap重写了NewNode方法,使节点是一个双向链表节点。
HashMap的NewNode方法:
Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
return new Node<>(hash, key, value, next);
}
//HashMap的内部类Node
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
LinkedHashMap的newNode方法:
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;
}
//LinkedHashMap的内部类Entry<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 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;
}
}