Collection接口
List接口
ArrayList
Array本质就是数组,在内部对数组进行动态扩容
/**
* Default initial capacity.
* 数组默认长度
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
* 空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
* 默认的空数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
* 内部存储数据元素的 数组对象
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial 集合中元素的个数
*/
private int size;
初始化
无参构造
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
//this.elementData={};
}
有参构造
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//创建指定长度的数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
//this.elementData={};
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
add方法
第一次添加
public boolean add(E e) {
//确定容量 动态扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
//将要添加的元素 添加到数组0的位置,size=1
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果无参构造 elementData={}
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 10 ,1 return 10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//有参构造,返回指定的长度
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //操作次数 自增
// minCapacity=10 - 0=10
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {//10
// overflow-conscious code
int oldCapacity = elementData.length;//0
// 0+0=0
int newCapacity = oldCapacity + (oldCapacity >> 1);
//0-10= -10
if (newCapacity - minCapacity < 0)
//newCapacity =10
newCapacity = minCapacity;
// 10 - (Integer.MAX_VALUE - 8)
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 创建一个长度为10的数组,将原来数组的值copy进去
elementData = Arrays.copyOf(elementData, newCapacity);
}
第2次添加
public boolean add(E e) {
//确定容量 动态扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
//将要添加的元素 添加到数组1的位置,size=2
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {//2
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//返回 2
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {//2
modCount++; //操作次数 自增
// minCapacity= 2 - 10
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
第11次添加
public boolean add(E e) {
//确定容量 动态扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
//将要添加的元素 添加到数组10的位置,size=11
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {//11
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {//11
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//返回 11
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {//11
modCount++; //操作次数 自增
// minCapacity= 11 - 10
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {//11
// overflow-conscious code
int oldCapacity = elementData.length;//10
// 10 +5 =15 1010 >> 1 = 101 = 5
int newCapacity = oldCapacity + (oldCapacity >> 1);
//15 - 11 = 4, 跳过,跳过
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 创建一个长度为15的数组,将原来数组的值copy进去
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));
}
set方法
public E set(int index, E element) {
//检查下标是否合法
rangeCheck(index);
//获取下标原来的值
E oldValue = elementData(index);
//新值赋值到下标位置
elementData[index] = element;
//返回原来的值
return oldValue;
}
reomve方法
public E remove(int index) {
//检查下标是否合法
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
//计算移动次数
int numMoved = size - index - 1;
//次数大于0
if (numMoved > 0)
//原数组,开始下标,目标数组,开始下标,长度
//把index+1后面的numMoved个元素复制到index的位置
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//空出的位置设置为null
elementData[--size] = null; // clear to let GC do its work
//返回删除的值
return oldValue;
}
LinkedList
LinkedList是通过双向链表实现的,具有双向链表的优缺点。顺序访问效率很高,随机访问效率比较低。它包含一个重要的私有内部静态类: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;
}
}
push方法
public void push(E e) {
addFirst(e);
}
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++;
}
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++;
}
get方法
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
Node<E> node(int index) {
//assert isElementIndex(index);
//index < size的一半,在前半部分
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;
}
}
set方法
public E set(int index, E element) {
//检查下标是否合法
checkElementIndex(index);
//根据下标获取对应的对象
Node<E> x = node(index);
//记录原来的值
E oldVal = x.item;
//设置新的值
x.item = element;
//返回原来的值
return oldVal;
}
Vector
和ArrayList类似,以动态数组的方式存储数据。Vector线程安全。每一个操作方法都加synchronized。灵活度低。
保证数据安全可以使用Collections工具类中的synchronizedxxx()方法实现。
Set接口
HashSet
底层数据结构时哈希表(哈希表不保证set的迭代顺序,特别是不保证数据永久不变),HashSet本质是一个没有重复元素的集合,允许null值。是通过HashMap实现的。HashSet中维护了一个HashMap类型的成员变量。
private transient HashMap<E,Object> map;
初始化
public HashSet() {
map = new HashMap<>();
}
add方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
本质是将数据保存到HashMap中,key 就是保存的内容,value是内部定义的一个Object对象。
TreeSet
基于TreeMap的NavigableSet实现。使用元素的自然顺序对元素进行排序,或者根据创建TreeSet时指定的Compartor进行排序
初始化
public TreeSet() {
this(new TreeMap<E,Object>());
}
add方法
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
本质是将数据保存到TreeMap中,key 就是保存的内容,value是内部定义的一个Object对象。
集合中的FailFast机制
java集合类为了应对并发访问,在集合迭代过程中,内部结构发生变化的一种防护措施,这种错误检查机制,为这种可能发生的错误,通过抛出java.util.ConcurrentModifycationException处理。
//迭代前,把修改次数赋值给变量expectedModCount
int expectedModCount = modCount;
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
//如果迭代过程中两个变量值不相等,说明集合被修改
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}