List源码分析
List
List 是继承Colection的接口 我们主要学习他的实现类 ArrayList 和 LinkedList
ArrayList
ArrayList是基于数组实现的 与数组不同的是 它可以存放不同的数据类型的数据而且长度不定
// 我们分析一下他的底程实现
// 添加过程
public boolean add(E e) {// add方法就是我往里面添加元素
ensureCapacityInternal(size + 1); //确定内部容量
elementData[size++] = e;// 往数组里面添加元素e
return true;//添加成功后返回true
}
// 如何做到长度可变
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // 数据是Object类型的所以可以存放任意类型的数据
private static final int DEFAULT_CAPACITY = 10;
// 首先 他通过ensureCapacityInternal方法得到一个最小容量
// 如果我们创建了一个空ArrayList 那么他的默认容量就是10
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//然后将得到的最小容量传到ensureExplicitCapacity方法中
ensureExplicitCapacity(minCapacity);
}
//
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 如果我们最小长度大于elementData的长度就增长 也就是执行grow(minCapacity)
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
// 这段代码的意思就是 给个新长度 重新创建一个数组 将原来的数组拷贝到新数组
// 获取原来数组的长度
int oldCapacity = elementData.length;
// 定义一个新长度等于 旧长度加新长度的一半
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);
}
LinkedList
LinkedList 是基于链表实现的 也是可以存储不同类型的数据 长度不定
具体实现过程是创建一个Node类 类中有三个字段 一个保存我们要存入的数据 一个保存链表前一个对象的地址值 一个保存下一个对象的地址值 Node源码如下
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
// 添加过程 我们调用add添加的时候是直接调用的linkLast(e) 末尾添加
public boolean add(E e) {
linkLast(e);
return true;
}
// 末尾添加
void linkLast(E e) {
final Node<E> l = last;// l是我们没放入数据是的最后一个对象
final Node<E> newNode = new Node<>(l, e, null);// 创建一个新Node对象
last = newNode;
if (l == null) // 如果l不存在 那么我们创建的对象就是第一个
first = newNode;
else // 如果存在就把我们新创建的对象的地址值给上一个对象 就形成了链表
l.next = newNode;
size++;
modCount++;
}