Collection集合
List
ArrayList
属性
// 默认初始化长度
private static final int DEFAULT_CAPACITY = 10;
// 空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
// 默认空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 已构建的数组
transient Object[] elementData;
// 数组长度
private int size;
/**
* AbstractArrayList中对象,已经修改的次数
* ArrayList 继承与 AbstractArrayList
*/
protected transient int modCount = 0;
初始化
// 1.无参构造 创建一个默认的空数组对象
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 2.初始化长度构造 创建一个指定长度的数组对象
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 指定长度为0,则创建空数组对象
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
// 3.参数为集合的构造
public ArrayList(Collection<? extends E> c) {
// 将集合转换为数组对象
Object[] a = c.toArray();
if ((size = a.length) != 0) {
// 集合若为ArrayList类型,则直接转换为当前对象
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
// 将转换后的数组复制,复制后的值构建为当前的ArrayList对象
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
add方法
// 添加单个元素
public boolean add(E e) {
/**
* 1. 校验数组长度,并修改数组已被修改的值
* 2. 新增元素添加到数组中
*/
ensureCapacityInternal(size + 1); // Increments modCount!!
// 将元素添加到最后一位可用空间中
elementData[size++] = e;
return true;
}
/**
* 添加元素到指定的索引位置
* 1.校验下标是否满足当前集合
* 2.
*/
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
// 将指定index下标及以后的元素向后移动
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
// 将index下标的值赋值到数组中
elementData[index] = element;
size++;
}
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
数组新增前的校验和扩容操作:
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// 返回数组的长度
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 校验当前数组是否为空数组对象
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 比较默认长度与当前最小长度,返回最大值
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// 确保数组长度,若数组无可用长度,则需要将数组进行扩容
private void ensureExplicitCapacity(int minCapacity) {
// 修改次数加1
modCount++;
// overflow-conscious code
// 所需最小长度与当前数组的最大长度进行比较,判断是否需要对数组进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
// 当前数组的最大长度
int oldCapacity = elementData.length;
// 新数组的最大长度,对当前数组进行0.5倍的扩容
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
// 若长度超过可创建数组长度的最大值
// 则返回可创建数组的最大值
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 将老数组中的数据拷贝到新创建的数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
remove方法
// 删除数组中指定下标的元素
public E remove(int index) {
// 校验当前下标是否超出数组的范围
rangeCheck(index);
// 数组被修改次数加 1
modCount++;
// 取出将要删除的值
E oldValue = elementData(index);
// 需要被删除的元素在数组中的下标值
int numMoved = size - index - 1;
if (numMoved > 0)
// 将数组中指定index+1位置以后的元素像前移动
System.arraycopy(elementData, index+1, elementData, index, numMoved);
// 将数组中最后一位元素置为空,方便jvm回收
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
// 删除指定元素
public boolean remove(Object o) {
if (o == null) {
// 删除元素为空时,遍历数组,删除为空的元素
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
// 遍历数组,删除数组中指定的元素的值
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
// 数组中删除元素的逻辑
private void fastRemove(int index) {
// 数组被修改次数加 1
modCount++;
// 需要被删除的元素在数组中的下标值
int numMoved = size - index - 1;
if (numMoved > 0)
// 将数组中指定index+1位置以后的元素像前移动
System.arraycopy(elementData, index+1, elementData, index,numMoved);
// 将数组中最后一位元素置为空,方便jvm回收
elementData[--size] = null; // clear to let GC do its work
}
LinkedList
属性
// 链表长度
transient int size = 0;
// 首节点
transient Node<E> first;
// 尾节点
transient Node<E> last;
/**
* AbstractArrayList中对象,已经修改的次数
* ArrayList 继承与 AbstractArrayList
*/
protected transient int modCount = 0;
初始化
// 无参构造,创建链表
public LinkedList() {}
// 含参数构造,参数为集合对象
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
// addAll方法,将集合数据添加到链表上
// 使用尾插法,依次添加
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
/**
* 添加集合到链表中
*
* @param index 待插入结点的位置
* @param c 需要插入的集合数据
*/
public boolean addAll(int index, Collection<? extends E> c) {
// 判断指定结点位置是否满足在链表中
checkPositionIndex(index);
// 待插入集合转换为数组对象
Object[] a = c.toArray();
// 待插入数组的长度
int numNew = a.length;
if (numNew == 0)
return false;
// 临时节点,pre上一个节点,succ当前节点
Node<E> pred, succ;
// 插入结点位置为尾部结点
if (index == size) {
succ = null;
pred = last;
} else {
// 插入结点位置为中间部分节点
succ = node(index);
pred = succ.prev;
}
// 遍历插入结点
for (Object o : a) {
@SuppressWarnings("unchecked")
E e = (E) o;
// 创建新节点
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode;
else
pred.next = newNode;
// 新节点插入,指针向后移动
pred = newNode;
}
// 将断开的链表链接到插入后的节点上
if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
}
// 修改链表长度
size += numNew;
// 修改集合修改次数
modCount++;
return true;
}
add方法
// 新增
public boolean add(E e) {
linkLast(e);
return true;
}
// 使用尾插法进行新增
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
// 在链表首部插入结点
public void addFirst(E e) {
linkFirst(e);
}
// 使用头插法插入结点
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
remove方法
空参删除:remove()
删除的节点为首节点数据
// 删除节点元素
public E remove() {
return removeFirst();
}
// 删除首个节点元素
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
删除第一个元素:removeFirst()
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
首节点断链
// 将首节点与链表进行断链操作
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
删除指定对象:remove(Object o)
// 删除链表中指定元素
public boolean remove(Object o) {
// 待删除元素是否为空
if (o == null) {
// 从首节点依次遍历
for (Node<E> x = first; x != null; x = x.next) {
// 校验是否是待删除元素
if (x.item == null) {
// 断链操作,进行删除
// 具体见断链操作
unlink(x);
return true;
}
}
} else {
// 待删除元素不为空
for (Node<E> x = first; x != null; x = x.next) {
// 校验是否为待删除元素
if (o.equals(x.item)) {
// 断链操作,进行删除
// 具体见断链操作
unlink(x);
return true;
}
}
}
return false;
}
删除指定位置元素:remove(int index)
public E remove(int index) {
// 校验指定位置是否在链表中
checkElementIndex(index);
// 断链操作,进行删除
// 具体见断链操作
return unlink(node(index));
}
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
Node<E> node(int index) {
// assert isElementIndex(index);
// 判断当前位置是在前半部分还是后半部分
// 遍历链表进行查找元素
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
断链操作
// 断链删除元素
// x节点不为空
E unlink(Node<E> x) {
// assert x != null;
// 当前节点值
final E element = x.item;
// 当前节点的下一个节点
final Node<E> next = x.next;
// 当前节点的上一个节点
final Node<E> prev = x.prev;
// 当前节点的上一个节点为空,则当前节点为首节点
if (prev == null) {
// 将下一个节点置为首节点
first = next;
} else {
// 将当前节点的上一个节点的next指针指向当前节点的下一个节点
// (图解:微信图片_20210316145013.png)
prev.next = next;
x.prev = null;
}
// 当前节点的下一个节点为空,则当前节点为尾节点
if (next == null) {
// 将上一个节点置为尾部节点
last = prev;
} else {
// 将当前节点的
// 图解:(微信图片_2021031614501.png)
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}
删除尾结点:removeLast()
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
// 尾结点断链操作
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
删除首次出现:removeFirstOccurrence(Object o)
public boolean removeFirstOccurrence(Object o) {
// 调用删除方法
return remove(o);
}
Map
HashMap
属性
// ====================默认配置===================================
/**
* 默认的初始化长度,必须为2的幂次方
* The default initial capacity - MUST be a power of two.
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/**
* 最大长度 ,最大为2的30次幂
* The maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
* MUST be a power of two <= 1<<30.
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
/**
* 默认的负载因子
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* 链表转换为红黑树的条件值
* The bin count threshold for using a tree rather than list for a
* bin. Bins are converted to trees when adding an element to a
* bin with at least this many nodes. The value must be greater
* than 2 and should be at least 8 to mesh with assumptions in
* tree removal about conversion back to plain bins upon
* shrinkage.
*/
static final int TREEIFY_THRESHOLD = 8;
/**
* 红黑树转换为链表的条件值
* The bin count threshold for untreeifying a (split) bin during a
* resize operation. Should be less than TREEIFY_THRESHOLD, and at
* most 6 to mesh with shrinkage detection under removal.
*/
static final int UNTREEIFY_THRESHOLD = 6;
/**
* 链表转换为红黑树时,数组的最小容量
* 若数组长度小于这个值时,不会存在树化的操作
* The smallest table capacity for which bins may be treeified.
* (Otherwise the table is resized if too many nodes in a bin.)
* Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
* between resizing and treeification thresholds.
*/
static final int MIN_TREEIFY_CAPACITY = 64;
/* ---------------- Fields -------------- */
/**
* 数组,初次使用时初始化,长度始终是2的幂次方
* The table, initialized on first use, and resized as
* necessary. When allocated, length is always a power of two.
* (We also tolerate length zero in some operations to allow
* bootstrapping mechanics that are currently not needed.)
*/
transient Node<K,V>[] table;
/**
* 键值对的集合
* Holds cached entrySet(). Note that AbstractMap fields are used
* for keySet() and values().
*/
transient Set<Map.Entry<K,V>> entrySet;
/**
* map中key-value键值对的数量
* The number of key-value mappings contained in this map.
*/
transient int size;
/**
* 集合修改次数
* The number of times this HashMap has been structurally modified
* Structural modifications are those that change the number of mappings in
* the HashMap or otherwise modify its internal structure (e.g.,
* rehash). This field is used to make iterators on Collection-views of
* the HashMap fail-fast. (See ConcurrentModificationException).
*/
transient int modCount;
/**
* 下一个要调整的长度值(capacity * load factor)
* The next size value at which to resize (capacity * load factor).
*
* @serial
*/
// (The javadoc description is true upon serialization.
// Additionally, if the table array has not been allocated, this
// field holds the initial array capacity, or zero signifying
// DEFAULT_INITIAL_CAPACITY.)
int threshold;
/**
* 表的负载因子
* The load factor for the hash table.
*
* @serial
*/
final float loadFactor;
定义的数据结构
Node
static class Node<K,V> implements Map.Entry<K,V> {
// 节点的hash值
final int hash;
// 键值对中的key值
final K key;
// 键值对中的value值
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;
}
//...包含get、set、hashCode和toString方法
}
TreeNode
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
TreeNode<K,V> parent; // red-black tree links
TreeNode<K,V> left;
TreeNode<K,V> right;
TreeNode<K,V> prev; // needed to unlink next upon deletion
boolean red;
TreeNode(int hash, K key, V val, Node<K,V> next) {
super(hash, key, val, next);
}
// ... 节点中方法
}
// LinkedHashMap.Entry
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);
}
}
初始化
// 空参构造,指定默认的负载因子
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
// 指定初始化长度的构造方法
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
/**
* 指定初始化长度和负载因子的构造方法
*
* @param initialCapacity 初始化长度
* @param loadFactor 负载因子
*/
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
// 参数为集合的构造方法
// 默认负载因子
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);
}
/**
* Implements Map.putAll and Map constructor.
* 在putAll中和构造方法中调用
*
* @param m the map
* @param evict false when initially constructing this map, else
* true (relayed to method afterNodeInsertion).
* false为初始化调用, true为非初始化调用
*/
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
int s = m.size();
if (s > 0) {
// 集合为空时
if (table == null) { // pre-size
// 计算当前需要的map集合长度
// HashMap底层的table在entry_count>table_size*load_factory时会扩容。
// 为了不让HashMap扩容,需要table_size >= entry_count / load_factor。
// 公式((float)s / loadFactor) + 1.0F中的size是使用float计算的,+1.0F是因为((float)s / loadFactor)使用float计算,在转换成整数的时候会进行舍入
// 为了保证最终计算出来的size足够大不至于触发扩容,所以进行了+ 1.0F操作
float ft = ((float)s / loadFactor) + 1.0F;
// 所需长度与最大长度比较
int t = ((ft < (float)MAXIMUM_CAPACITY) ? (int)ft : MAXIMUM_CAPACITY);
if (t > threshold)
// 扰动函数,重新计算扩容需要的长度
threshold = tableSizeFor(t);
}
else if (s > threshold)
// 扩容操作
resize();
// 遍历待插入的集合,将元素保存到新的集合中
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
K key = e.getKey();
V value = e.getValue();
putVal(hash(key), key, value, false, evict);
}
}
}
put方法
// 保存元素
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
putVal方法
/**
*
* @param hash 集合map中key的hash值
* @param key 键值对中的key值
* @param value 键值对中的value值
* @param onlyIfAbsent (true/false) 当为true时,不修改当前值
* @param evict false为初始化调用, true为非初始化调用
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
// tab 数组对象、p 数组中的数据节点、n 数组长度、i 数组中的下标
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
// 数组为空或者长度为0,则初始化数组
n = (tab = resize()).length;
// 判断新增的key在对应位置是否有数据
// 是否发生hash冲撞
if ((p = tab[i = (n - 1) & hash]) == null)
// 将新添加的元素存放到数组中
tab[i] = newNode(hash, key, value, null);
else {
// 发生hash冲撞
// p是原数据节点
Node<K,V> e; K k;
// p.hash == hash 原数据节点的hash值与新存入节点的hash值相同
// (k = p.key) == key 原数据节点的key值与新存入节点的key地址值相同
// (key != null && key.equals(k)) 新存入节点不为null,并且与原节点的值相同
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
// 新存入的节点的key在map中存在,取出已存在的节点p
e = p;
else if (p instanceof TreeNode)
// 判断是否为树节点
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
//
for (int binCount = 0; ; ++binCount) {
// 线性探地址法,找到空闲位置进行节点保存
if ((e = p.next) == null) {
// 创建节点
p.next = newNode(hash, key, value, null);
// 判断链表长度是否到8,进行树化操作
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
// 链表转化为红黑树
treeifyBin(tab, hash);
break;
}
// 探地址法搜寻的节点是否与当前节点的key值相同,相同则跳出循环
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
break;
// 指针后移操作
p = e;
}
}
// map中已存在的节点不为空
if (e != null) { // existing mapping for key
V oldValue = e.value;
// 是否更新值,若onlyIfAbsent为false或者已存在节点的值为空,更新当前key对应的值
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
// 修改被修改次数
++modCount;
// 判断当前长度是否需要扩容
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
扩容:resize()
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
// 获取节点数组长度
int oldCap = (oldTab == null) ? 0 : oldTab.length;
// 扩容的阈值
int oldThr = threshold;
int newCap, newThr = 0;
// 校验是否是第一次初始化
if (oldCap > 0) {
// 原始节点数组长度是否到达最大长度
if (oldCap >= MAXIMUM_CAPACITY) {
// 大于最大长度,不进行操作
threshold = Integer.MAX_VALUE;
return oldTab;
}
// 扩容后长度 = 原始长度 * 2
// 校验新的长度是否达到最大长度
// 原始长度是否大于等于默认初始化长度(16)
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
// 扩容后的阈值 = 原始阈值 * 2
newThr = oldThr << 1; // double threshold
}
else if (oldThr > 0) // initial capacity was placed in threshold
// 原数组长度为0,扩容阈值大于0时,将阈值赋值给节点数组的初始化长度
newCap = oldThr;
else { // zero initial threshold signifies using defaults
// map的无参构造,首次初始化
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
// 新的阈值为0,则进行阈值的重新计算
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
// 阈值重新赋值
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
// 创建新的节点数组
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
if (oldTab != null) {
// 原始数组数据的迁移,遍历原节点数组
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
if ((e = oldTab[j]) != null) {
// 取出原始数组中的数据,并将原始数组对应索引位置的数据置为null
oldTab[j] = null;
if (e.next == null)
// 当前节点是单独的节点,指向下一个节点的指针为null
// 重新计算hash值,存放到新的节点数组中
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
// 取树节点
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
// 节点的hash值与原始长度做&运算,等于0则位于低位,不等于0则处于高位
// 将新的数组,按照原始长度分为两部分,大于的设为高位区,小于设为低位区
// 将原始数组中的链表重新计算,低位则存在低位区,高位则存在高位区
// 低位链表头结点,低位链表尾节点
Node<K,V> loHead = null, loTail = null;
// 高位链表头结点,高位链表尾节点
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
// 低节点数据处理
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
// 高节点数据处理
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
// 数据迁移到新的节点数组中
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
// 树节点转换
final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) {
TreeNode<K,V> b = this;
// Relink into lo and hi lists, preserving order
// 低位节点
TreeNode<K,V> loHead = null, loTail = null;
// 高位节点
TreeNode<K,V> hiHead = null, hiTail = null;
int lc = 0, hc = 0;
// 遍历树节点,将原树形节点结构,转换成链表结构
for (TreeNode<K,V> e = b, next; e != null; e = next) {
next = (TreeNode<K,V>)e.next;
e.next = null;
if ((e.hash & bit) == 0) {
if ((e.prev = loTail) == null)
loHead = e;
else
loTail.next = e;
loTail = e;
++lc;
}
else {
if ((e.prev = hiTail) == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
++hc;
}
}
// 低位链表节点转换成树形节点
if (loHead != null) {
if (lc <= UNTREEIFY_THRESHOLD)
// TreeNode类型节点链表转换成Node类型节点链表
tab[index] = loHead.untreeify(map);
else {
// 链表树化操作
tab[index] = loHead;
if (hiHead != null) // (else is already treeified)
loHead.treeify(tab);
}
}
if (hiHead != null) {
if (hc <= UNTREEIFY_THRESHOLD)
// TreeNode类型节点链表转换成Node类型节点链表
tab[index + bit] = hiHead.untreeify(map);
else {
// 链表树化操作
tab[index + bit] = hiHead;
if (loHead != null)
hiHead.treeify(tab);
}
}
}
新增树节点:putTreeVal
/**
*
* @param map 集合对象
* @param tab 节点数组对象
* @param h key的hash值
* @param k 键值对的key
* @param v 键值对的value
*/
final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab, int h, K k, V v) {
Class<?> kc = null;
boolean searched = false;
// 获取树的根节点
TreeNode<K,V> root = (parent != null) ? root() : this;
// 遍历红黑树
for (TreeNode<K,V> p = root;;) {
int dir, ph;
K pk;
// 新存入节点hash值与当前树节点hash值比较
if ((ph = p.hash) > h)
// 左子树
dir = -1;
else if (ph < h)
// 右子树
dir = 1;
else
// 如果新存入节点与当前树节点相同,返回节点
if ((pk = p.key) == k || (k != null && k.equals(pk)))
return p;
else
// 校验键值对中key的类型是否为null:(kc == null && (kc = comparableClassFor(k)) == null)
// kc 为k的类型
if ((kc == null && (kc = comparableClassFor(k)) == null)
// 比较pk的类型与k的类型,再比较k与pk的值
|| (dir = compareComparables(kc, k, pk)) == 0) {
// 当前节点为新增节点
if (!searched) {
TreeNode<K,V> q, ch;
searched = true;
if (((ch = p.left) != null && (q = ch.find(h, k, kc)) != null)
|| ((ch = p.right) != null && (q = ch.find(h, k, kc)) != null))
return q;
}
// 判断新增的key是在左子树还是右子树
dir = tieBreakOrder(k, pk);
}
TreeNode<K,V> xp = p;
// 根据dir判断遍历左子树还是右子树
if ((p = (dir <= 0) ? p.left : p.right) == null) {
// 当前 p 节点是叶子节点
Node<K,V> xpn = xp.next;
TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn);
if (dir <= 0)
xp.left = x;
else
xp.right = x;
xp.next = x;
x.parent = x.prev = xp;
if (xpn != null)
((TreeNode<K,V>)xpn).prev = x;
// 新增节点保存到tab中,平衡插入树节点
moveRootToFront(tab, balanceInsertion(root, x));
return null;
}
}
}
// 获取根节点
final TreeNode<K,V> root() {
for (TreeNode<K,V> r = this, p;;) {
if ((p = r.parent) == null)
return r;
r = p;
}
}
// 比较k与x的值
// 若x为null或者x类型与k的类型不同,则返回0;否则返回k与x的比较的值
static int compareComparables(Class<?> kc, Object k, Object x) {
return (x == null || x.getClass() != kc ? 0 : ((Comparable)k).compareTo(x));
}
链表树化:treeifyBin
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
// 节点数组为null,节点数组长度小于64;进行扩容操作
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
// 获取节点数组中的node节点e
else if ((e = tab[index = (n - 1) & hash]) != null) {
// hd 树的首节点
TreeNode<K,V> hd = null, tl = null;
// 循环遍历链表,将链表转换成树节点
// 此时的hd并不是树,此时还是链表,只是链表中每个节点类型都为TreeNode类型
do {
// 将链表e节点转换成树p节点
TreeNode<K,V> p = replacementTreeNode(e, null);
if (tl == null)
// 记录树的首节点
hd = p;
else {
p.prev = tl;
tl.next = p;
}
tl = p;
// 指针后移
} while ((e = e.next) != null);
// 将节点数组中原有的链表节点替换为树节点
if ((tab[index] = hd) != null)
// 树化,转化成红黑树
hd.treeify(tab);
}
}
TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
return new TreeNode<>(p.hash, p.key, p.value, next);
}
// 转化成红黑树
final void treeify(Node<K,V>[] tab) {
TreeNode<K,V> root = null;
for (TreeNode<K,V> x = this, next; x != null; x = next) {
next = (TreeNode<K,V>)x.next;
x.left = x.right = null;
if (root == null) {
x.parent = null;
x.red = false;
root = x;
}
else {
K k = x.key;
int h = x.hash;
Class<?> kc = null;
for (TreeNode<K,V> p = root;;) {
int dir, ph;
K pk = p.key;
if ((ph = p.hash) > h)
dir = -1;
else if (ph < h)
dir = 1;
else if ((kc == null &&
(kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0)
dir = tieBreakOrder(k, pk);
TreeNode<K,V> xp = p;
if ((p = (dir <= 0) ? p.left : p.right) == null) {
x.parent = xp;
if (dir <= 0)
xp.left = x;
else
xp.right = x;
// 插入新节点,进行左旋或者右旋,保证树满足红黑树的特点
root = balanceInsertion(root, x);
break;
}
}
}
}
moveRootToFront(tab, root);
}
remove方法
根据key删除:remove(Object key)
public V remove(Object key) {
Node<K,V> e;
return (e = removeNode(hash(key), key, null, false, true)) == null ?
null : e.value;
}
删除指定键值对:remove(Object key, Object value)
public boolean remove(Object key, Object value) {
return removeNode(hash(key), key, value, true, true) != null;
}
removeNode(int hash, Object key, Object value,boolean matchValue, boolean movable)
final Node<K,V> removeNode(int hash, Object key, Object value, boolean matchValue, boolean movable) {
Node<K,V>[] tab; Node<K,V> p; int n, index;
// 节点数组存在,对应key的值不为null
if ((tab = table) != null && (n = tab.length) > 0 && (p = tab[index = (n - 1) & hash]) != null) {
Node<K,V> node = null, e; K k; V v;
// 获取到待删除的节点node的信息
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
node = p;
else if ((e = p.next) != null) {
if (p instanceof TreeNode)
node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
else {
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
node = e;
break;
}
p = e;
} while ((e = e.next) != null);
}
}
// 执行节点的删除操作
if (node != null && (!matchValue || (v = node.value) == value || (value != null && value.equals(v)))) {
if (node instanceof TreeNode)
((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
else if (node == p)
tab[index] = node.next;
else
p.next = node.next;
++modCount;
--size;
afterNodeRemoval(node);
return node;
}
}
return null;
}
removeTreeNode方法
final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab, boolean movable) {
int n;
if (tab == null || (n = tab.length) == 0)
return;
int index = (n - 1) & hash;
TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl;
TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev;
if (pred == null)
tab[index] = first = succ;
else
pred.next = succ;
if (succ != null)
succ.prev = pred;
if (first == null)
return;
if (root.parent != null)
root = root.root();
// 根节点为null
// movable为true 并且(根节点的右节点为空或者左节点为空或者左节点的左节点为空)
if (root == null
|| (movable && (root.right == null || (rl = root.left) == null || rl.left == null))) {
// 去树化操作
tab[index] = first.untreeify(map); // too small
return;
}
TreeNode<K,V> p = this, pl = left, pr = right, replacement;
if (pl != null && pr != null) {
TreeNode<K,V> s = pr, sl;
while ((sl = s.left) != null) // find successor
s = sl;
boolean c = s.red;
s.red = p.red;
p.red = c; // swap colors
TreeNode<K,V> sr = s.right;
TreeNode<K,V> pp = p.parent;
if (s == pr) { // p was s's direct parent
p.parent = s;
s.right = p;
}
else {
TreeNode<K,V> sp = s.parent;
if ((p.parent = sp) != null) {
if (s == sp.left)
sp.left = p;
else
sp.right = p;
}
if ((s.right = pr) != null)
pr.parent = s;
}
p.left = null;
if ((p.right = sr) != null)
sr.parent = p;
if ((s.left = pl) != null)
pl.parent = s;
if ((s.parent = pp) == null)
root = s;
else if (p == pp.left)
pp.left = s;
else
pp.right = s;
if (sr != null)
replacement = sr;
else
replacement = p;
}
else if (pl != null)
replacement = pl;
else if (pr != null)
replacement = pr;
else
replacement = p;
if (replacement != p) {
TreeNode<K,V> pp = replacement.parent = p.parent;
if (pp == null)
root = replacement;
else if (p == pp.left)
pp.left = replacement;
else
pp.right = replacement;
p.left = p.right = p.parent = null;
}
TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement);
if (replacement == p) { // detach
TreeNode<K,V> pp = p.parent;
p.parent = null;
if (pp != null) {
if (p == pp.left)
pp.left = null;
else if (p == pp.right)
pp.right = null;
}
}
if (movable)
moveRootToFront(tab, r);
}
扰动函数:tableSizeFor
// 计算出大于当前值的最小2的幂次方的值
// 图解:扰动函数.png
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
LinkedHashMap
属性
// 双向链表头结点
transient LinkedHashMap.Entry<K,V> head;
// 双向链表尾结点
transient LinkedHashMap.Entry<K,V> tail;
// 此链接的哈希映射的迭代排序方法:
// true 用于访问顺序,
// false 用于插入顺序。
final boolean accessOrder;
定义的数据结构
Entry
// 自定义结构类型,继承了HashM中的Node类型
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);
}
}
初始化
// 无参构造
public LinkedHashMap() {
super();
accessOrder = false;
}
// 初始化长度
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
// 初始化长度和负载因子
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
// 初始化长度、负载因子和迭代排序的类型
public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
// 参数为集合的初始化方法
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super();
accessOrder = false;
putMapEntries(m, false);
}
put方法 和 remove方法
同HashMap的put方法和remove(Object key)方法
// 继承了HashMap的put方法和remove(Object key)方法,
// 重写了newNode方法、
// newTreeNode方法、
// afterNodeAccess方法、
// afterNodeInsertion方法、
// afterNodeRemoval方法、
// replacementTreeNode方法
newNode 和 newTreeNode
// 创建节点
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;
}
// putTreeVal中的newTreeNode方法
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;
}
// 将新节点保存到双向链表中
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;
}
}
afterNodeAccess
// 将当前节点移到链表尾部
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;
}
}
afterNodeInsertion
// 删除头结点
// 此处应为扩展操作
void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry<K,V> first;
// evict 为false是初始化时候调用;true时为新增时调用
// 判断是否要删除头结点
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
// 删除节点
removeNode(hash(key), key, null, false, true);
}
}
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
afterNodeRemoval
// 删除双向链表中的节点
// 删除额外维护的链表中的已经删除的节点
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;
}
replacementTreeNode
// 替换为树节点
TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
TreeNode<K,V> t = new TreeNode<K,V>(q.hash, q.key, q.value, next);
transferLinks(q, t);
return t;
}
// 用dst节点替换src节点
private void transferLinks(LinkedHashMap.Entry<K,V> src, LinkedHashMap.Entry<K,V> dst) {
LinkedHashMap.Entry<K,V> b = dst.before = src.before;
LinkedHashMap.Entry<K,V> a = dst.after = src.after;
if (b == null)
head = dst;
else
b.after = dst;
if (a == null)
tail = dst;
else
a.before = dst;
}
遍历
LinkedHashMap中额外维护了一个双向链表,在遍历的时候,可以有序的取出存入的元素数据。
Set
HashSet
属性
// set集合保存数据的结构类型
private transient HashMap<E,Object> map;
// map对象中key-value中的value值
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
初始化
// 无参构造
public HashSet() {
map = new HashMap<>();
}
// 指定初始化长度
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
// 指定初始化长度和负载因子
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
// 指定初始化长度和负载因子和布尔值,为了区分HashSet(int initialCapacity, float loadFactor)构造方法
// (This package private constructor is only used by LinkedHashSet.)
// 依次方法创建一个LinkedHashMap对象,保证有序性
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
// 参数为集合的构造方法
public HashSet(Collection<? extends E> c) {
// 根据集合的长度,确定初始化的最大长度
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
// 集合保存到map中
addAll(c);
}
add方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
remove方法
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
LinkedHashSet
初始化
// 继承了HashSet,通过调用父类中 HashSet(int initialCapacity, float loadFactor, boolean dummy) 初始化方法,
// 创建一个LinkedHashMap对象,保证有序性的实现
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}