ArrayList源码分析
add()过程源码如下
// eg1:第一次新增元素e="a1",
public boolean add(E e) {
/** 确定是否需要扩容,如果需要,则进行扩容操作*/
ensureCapacityInternal(size + 1); // Increments modCount!!
// eg1:size=0,elementData[0]="a1",然后a自增为1
elementData[size++] = e;
return true;
}
// eg1:第一次新增元素,elementData={} minCapacity=1
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//检查elementData是否为空数组
// eg1:满足if判断,DEFAULT_CAPACITY=10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// eg1:第一次新增元素,minCapacity=10
private void ensureExplicitCapacity(int minCapacity) {
// eg1: modCount++后,modCount=1
modCount++;
/** 如果所需的最小容量大于elementData数组的容量,则进行扩容操作 */
if (minCapacity - elementData.length > 0) { // eg1:10-0=10,满足扩容需求
// eg1:minCapacity=10
grow(minCapacity);
}
}
// eg1:第一次新增元素,minCapacity=10,即:需要将elementData的0长度扩容为10长度。
private void grow(int minCapacity) {
/** 原有数组elementData的长度*/
int oldCapacity = elementData.length; // eg1:oldCapacity=0
/**
* A >> 1 等于 A/2
* eg: 3 >> 1 = 3/2 = 1
* 4 >> 1 = 4/2 = 2
* ------------------------
* A << 1 等于 A*2
* eg: 3 << 1 = 3*2 = 6
* 4 << 1 = 4*2 = 8
*
* 000100 >> 1 = 000010
* 000100 << 1 = 001000
*/
/** 新增oldCapacity的一半整数长度作为newCapacity的额外增长长度 */
int newCapacity = oldCapacity + (oldCapacity >> 1); // eg1:newCapacity=0+(0>>1)=0
/** 新的长度newCapacity依然无法满足需要的最小扩容量minCapacity,
则新的扩容长度为minCapacity */
if (newCapacity - minCapacity < 0) {
// eg1:newCapacity=10
newCapacity = minCapacity;
}
/** 新的扩容长度newCapacity超出了最大的数组长度MAX_ARRAY_SIZE */
if (newCapacity - MAX_ARRAY_SIZE > 0) {
newCapacity = hugeCapacity(minCapacity);
}
/** 扩展数组长度为newCapacity,并且将旧数组中的元素赋值到新的数组中 */
// eg1:newCapacity=10, 扩容elementData的length=10
elementData = Arrays.copyOf(elementData, newCapacity);
}
get()过程源码如下
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
private void rangeCheck(int index) {
if (index >= size) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
set()过程源码如下
public E set(int index, E element) {
//判断是否越界
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
remove()过程源码如下:
public E remove(int index) {
/** 校验传入的参数index是否超出了数组的最大下标,
如果超出,则抛出:IndexOutOfBoundsException异常*/
rangeCheck(index);
modCount++;
// eg1:String oldValue="a1"
E oldValue = elementData(index);
// eg1:numMoved=4-0-1=3
int numMoved = size - index - 1;
if (numMoved > 0) {
/** 从需要删除的index后一位开始到末尾的这部分数据,整体都向前移动一个元素。*/
System.arraycopy(elementData, index + 1, elementData, index,
numMoved);
}
// 通知jvm将之前的最后一位元素进行垃圾回收
elementData[--size] = null; // clear to let GC do its work
return oldValue; // 返回已被删除的元素
}
LinkedList源码分析
add() 过程源码
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
// eg1: newNode null<--"a1"-->null
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
// eg1: l=null
if (l == null) {
/** 如果是第一个添加的元素,则first指针指向该结点*/
first = newNode; // eg1: first指向newNode
} else {
/** 如果不是第一个添加进来的元素,则更新l的后置结点指向新添加的元素结点*/
l.next = newNode;
}
size++;
modCount++;
}
HashMap源码分析
final Node<K, V>[] resize() {
Node<K, V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap = 0;
int newThr = 0;
/** 第一步:根据情况,调整新表的容量newCap和阈值newThr*/
if (oldCap > 0) {
/** 如果老table的长度大于等于2^30(1 << 30) 1后面有30个0*/
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE; /** 2^31-1 1后面有30个1 */
return oldTab;
}
/** 如果将老Table的长度增长2倍作为新的容量长度(newCap),是否小于2^30(1 << 30) 并且 老Table长度是否大于等于16(1 << 4)*/
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) {
// eg6: newCap=32, newThr=24
newThr = oldThr << 1;
}
} else if (oldThr > 0) {
newCap = oldThr;
} else {
// eg1: oldCap=0 newCap=16 newThr=0.75f*16=12
newCap = DEFAULT_INITIAL_CAPACITY; /** 默认【表容量】为16(1 << 4) */
newThr = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); /** 默认【阈值因子】为0.75f */
}
if (newThr == 0) {
float ft = (float) newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float) MAXIMUM_CAPACITY ? (int) ft : Integer.MAX_VALUE);
}
threshold = newThr;
/** 第二步:根据newCap和newThr,构建新数组 */
/** 初始化新表*/
@SuppressWarnings({"rawtypes", "unchecked"})
Node<K, V>[] newTab = (Node<K, V>[]) new Node[newCap];
table = newTab;
if (oldTab != null) { /** 如果老的table里有数据,则进行数据迁移*/
for (int j = 0; j < oldCap; ++j) {
Node<K, V> e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null) { /** 没有后置节点,说明e是最后一个节点*/
newTab[e.hash & (newCap - 1)] = e;
} else if (e instanceof TreeNode) { /** e是树节点*/
((TreeNode<K, V>) e).split(this, newTab, j, oldCap);
} else {
Node<K, V> loHead = null;
Node<K, V> loTail = null;
Node<K, V> hiHead = null;
Node<K, V> hiTail = null;
Node<K, V> next;
do {
next = e.next; /** 获得oldTab数组下标的Node列表的下一个节点*/
if ((e.hash & oldCap) == 0) {
/** 计算e在老表oldTab的下标,如果是第一个Node,即:下标index==0*/
if (loTail == null) {
/** 将loHead指向oldTab数组第一个下标的第一个元素e*/
loHead = e;
} else {
loTail.next = e;
}
/** 将loTail指向oldTab数组第一个下标的最后一个元素e*/
loTail = e;
}
else { /** 如果不是oldTab中的第一个下标Node*/
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;
}