![](https://img.haomeiwen.com/i13790592/b9b3d87476446d22.png)
Iterable:
实现这个接口的类可以和增强for循环一起使用
// 返回这个类的迭代器
Iterator<T> iterator();
Collection:
这个接口是所有集合的父接口,定义规范了所有集合的行为
public boolean add(E object);
public boolean addAll(Collection<? extends E> collection);
public void clear();
public boolean contains(Object object);
//判断collection是否全部在当前集合中
public boolean containsAll(Collection<?> collection);
public boolean equals(Object object);
public boolean isEmpty();
public Iterator<E> iterator();
public boolean remove(Object object);
// 去除当前集合中collection中的元素
public boolean removeAll(Collection<?> collection);
// 在当前集合中保留collection中的元素(取交集)
public boolean retainAll(Collection<?> collection);
public int size();
// 将这个集合中所有的数据当做数组返回
public Object[] toArray();
ArrayList:
ArrayList的底层是一个数组,特点是增删慢,查找快,线程不安全;
ArrayList类中的变量
// 底层数组的默认大小
private static final int DEFAULT_CAPACITY = 10;
// 存放数据的个数
int size;
// 底层数组对象
transient Object[] elementData;
// 一个空的数组,用来初始化上面的elementData对象
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient:transient关键字修饰的变量不参与序列化过程
ArrayList():
// 给array对象赋值一个空的数组
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
新建一个ArrayList对象,会为底层的数组赋值一个空的obj数组
add():
public boolean add(E e) {
// 判断size+1是否超过数组容量,超过就扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
// 如果elementData是第一次在构造方法中赋值的空数组,首次初始化10个大小
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
// 数组size改变的次数(存放在AbstractList中)
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
// 如果当前需要的容量大于数组的实际容量,执行扩容逻辑
grow(minCapacity);
}
// 数组最大容量 , 一些jvm需要存放一些head words
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 数组扩容核心代码
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 新容量等于旧容量的1.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);
}
// 如果这次扩容的新大小大于数组最大值(max-8)
private static int hugeCapacity(int minCapacity) {
// 如果超过int的max,overflow
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
// 如果还没有超过max将新容量调整到max
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
add操作:在添加操作中,首先会判断当前size+1后是否超过底层数组的容量,如果是第一次add,将底层数组的容量默认扩容为10个大小,当第十一次添加的时候(需要的大小11>底层数组的大小10)进行扩容处理,新的底层数组大小变成旧数组的1.5倍,底层数组容量的最大值是max-8,但是如果超过这个数,还是能继续扩充到max的,当超过max就会溢出,OutOfMemoryError;
get():
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
get操作很简单,判断index是否合法,返回数组的第index个元素
remove(int index):
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
remove操作调用了java的一个native方法,arraycopy(Object src, int srcPos, Object dest, int destPos,int length),各个参数的含义:
- src:需要复制的数组
- srcPos:src的开始下标
- dest:返回的结果数组
- destPos:dest的开始下标(从哪里开始复制)
- length:复制的长度
remove的思路是将下标index的元素丢弃,然后将index到size-1的元素通过arraycopy全部向前移动一个单位,将最后一个元素置为null等待gc回收
remove(Object o):
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;
}
remove(obj)通过循环找到obj对象的index,再通过index和arraycopy删除元素,fastRemove同上面的remove(index),只不过省去了保存obj的逻辑;
clear()
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
简单易懂
网友评论