集合
集合主要分为两组(单列集合和双列集合),collection接口有两个子接口,实现的子类均为单列集合。
Map接口的实现的子类均为双列集合
单列集合之ArrayList
ArrayList底层是由数组实现的,允许加入null(多个也允许),线程不安全,下图以ArrayList的add方法为例,可见并没有做线程同步。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
ArrayList中维护了一个Object类型的数组elementData
无参构造创建ArrayList
创建了一个空的ArrayList
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
add方法
public boolean add(E e) {
// size是ArrayList类私有变量
ensureCapacityInternal(size + 1); // 确认容量够不够
elementData[size++] = e;
return true;
}
判断数组是否为空
private void ensureCapacityInternal(int minCapacity) {
//比较一下
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/**
* @param 对象数组elementData,最小容量minCapacity
* @return 所需最小容量
*/
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 如果是第一次赋值,即elementData是空数组
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// //给一个默认容量DEFAULT_CAPACITY(10)
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //记录当前集合被修改的次数,如果有多个线程同时修改会异常
// overflow-conscious code
// 如果实际需要的最小容量比能提供的容量要大,就需要扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
扩容函数grow
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// oldCapacity 右移一位即1/2,所以第一次是0
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果扩容后的容量还是小于所需的,就直接按照所需的来设置容量
//这里其实算是为了修正第一次的0 + 0/2还是0 的bug
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果比默认的最大值还大,就调用hugeCapacity
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 这里使用copyOf是为了在扩容的时候仍然保留原来的元素
elementData = Arrays.copyOf(elementData, newCapacity);
}
有参构造创建ArrayList
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
输入参数是ArrayList的初始大小,因为第一次初始化 this.elementData = new Object[initialCapacity] 就是有大小的数组,因此调用grow扩容的时候第一次就直接按照实际大小的1.5倍来扩容。
小tips:
目录
IDEA的FILES->Setting->中吧这个选项去掉可以看到完整的集合内部信息,而不是简化后的元素信息