ArrayList
接上文,ArrayList实际上是List接口的实现类,底层实际上是数组,但该数组可以调整大小。
泛型
<E>是一种特殊的引用数据类型——泛型,泛型的用途很广,在本文就简单做一介绍,后续出专门的文章来解释泛型。泛型的“<>”中可以是任何数据类型,但其类型参数是在创建泛型类对象的时候就已经确定(例如ArrayList<Integer>),因为静态成员方法和变量是在类加载时就已经初始化,直接使用类名调用,因此在泛型的类型参数未确定时,静态成员有可能被调用,所以泛型的类型参数不能在静态成员中使用。
ArrayList常用方法
//泛型定义为String类型
ArrayList<String> arrayList = new ArrayList<>();
//将指定的参数元素添加到集合
arrayList.add("唐三");
arrayList.add("小舞");
arrayList.add("马红俊");
//在指定的地方插入元素
arrayList.add(1,"唐昊");
//创建一个新集合
ArrayList<String> arrayList1 = new ArrayList<>();
arrayList1.add("朱竹清");
arrayList1.add("奥斯卡");
arrayList1.add("戴沐白");
//将新集合所有元素添加到原集合
arrayList.addAll(arrayList1);
//获取集合元素个数
arrayList.size();
//获取指定索引的元素
arrayList.get(1);
ArrayList底层扩容实现原理:
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// preconditions not checked because of inlining
// assert oldLength >= 0
// assert minGrowth > 0
int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow
if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
return prefLength;
} else {
// put code cold in a separate method
return hugeLength(oldLength, minGrowth);
}
}
底层扩容关键源码如上,其中可以发现当创建ArrayList对象时,如果使用的是无参构造器,初始的容量为0,第一次添加容量为10,如需要再此添加,则按1.5倍数扩充;如果使用的是指定大小的构造器,则初始的容量为指定大小,如果需要扩容,则直接按1.5倍扩容。
Vector
Vector底层是一个对象数组,protected Object[] elementData;
Vector是线程同步的,线程安全,在开发中,需要线程同步安全时,往往采用Vector
//无参构造器
public Vector() {
this(10);
}
public synchronized boolean add(E e) {
modCount++;
add(e, elementData, elementCount);
return true;
}
public synchronized void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
modCount++;
if (minCapacity > elementData.length)
grow(minCapacity);
}
}
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
capacityIncrement > 0 ? capacityIncrement : oldCapacity
/* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
}
Vector底层源码解读可知,如果是无参,默认为10,满后,按2倍扩容,指定大小后每次直接按照2倍扩容。
Vector与ArrayList比较
底层结构 | 版本 | 线程安全与效率 | 扩容倍数 | |
ArrayList | 可变数组 | jdk1.2 | 不安全,效率高 | 有参:1.5倍数 无参:第一次10, 第二次按1.5倍扩充 |
Vector | 可变数组Object[] | jdk1.0 | 安全,效率不高 | 无参,默认10,满后按两倍扩容 指定大小,每次直接2倍数扩充 |