ArrayList
首先看下ArrayList的对象属性结构:
private static final int DEFAULT_CAPACITY = 10; //默认长度
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // non-private to simplify nested class access
private int size; //元素个数
可见ArrayList底层是数组结构,且数组默认长度是10
常见构造器:
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);
}
}
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
可见当使用ArrayList arrayList = new ArrayList();初始化对象的时候,里面的数组是一个{}空数组
当我们使用ArrayList arrayList = new ArrayList();来初始化对象的时候,数组的初始化有点奇怪,加入现在add第一个值
现在来看看add过程:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
size是list中元素的个数,并不是数组的大小 插入第一个值这里应该是size = 0
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
此时当前数组为{},则minCapacity = 10;
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
此时minCapacity = 10;elementData为{} 则elementData.length == 0 ,则minCapacity - elementData.length > 0 为true
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //oldCapacity = 0
int newCapacity = oldCapacity + (oldCapacity >> 1);//newCapacity = 0
if (newCapacity - minCapacity < 0) //0 - 10 = -10 < 0
newCapacity = minCapacity; // newCapacity = 10
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);
}
elementData = Arrays.copyOf(elementData, newCapacity);则初始化一个新的数组,大小为10
所以初始化数组操作比较多,所以我们一般采用ArrayList arrayList = new ArrayList(10);来初始化
初始化后,继续插入过程跟上述差不多,这里记住两个要素:
1、扩容条件:minCapacity - elementData.length > 0 当前元素个数 size +1 > 当前数组容量时
2、扩容增长倍数:oldCapacity + (oldCapacity >> 1) 新数组为原数组的1.5倍
remove过程:
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;
}
来看个例子:
public class ArrayListTest {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(10);
arrayList.add("aaaa");
arrayList.add(null);
arrayList.add(null);
System.out.println(arrayList.size());
arrayList.remove(null);
System.out.println(arrayList.size());
}
}
如果list中有重复元素,可见remove只会删除其中一个匹配的,这个在项目开发中要切记
private void fastRemove(int index) {
modCount++;
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
}
删除元素,会引起数据的位移,而且把elementData[--size] 置Null
vector
来看下属性有哪些:
protected Object[] elementData;
protected int elementCount; //元素个数
protected int capacityIncrement;//扩容的增长量
可见其底层也是一个数组结构
构造器有:
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
public Vector() {
this(10);
}
这个跟ArrayList有一点区别:Vector vector = new Vector();会默认初始化一个10长度的数组
add过程:
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
方法加了synchronized 说明vector的插入是线程安全的
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
这里跟arrayList一样,当前元素个数+1>数组容量就会执行扩容操作
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
这是capacityIncrement 是可以Vector(int initialCapacity, int capacityIncrement)构造器传入的,如果没有传入,则默认是0;
则如果capacityIncrement == 0 ,则扩容是2倍扩容
如果capacityIncrement > 0 ,则扩容后的长度是老数组的长度+capacityIncrement
remove操作跟arrayList操作差不多,只不过加了synchronized是线程安全的
总结
1、new ArrayList();会初始化一个{}空数组,当插入第一个元素,才会初始化一个默认长度为10的数组
new Vector();会默认初始化一个10长度的数组,自增量为0
2、Vector 可以设置扩容的自增量,且当自增量为0时,时按两倍增长,ArrayList不能设置自增量,按1.5倍增长
3、Vector ,arrayList 根据元素寻找index,都是轮询整个数组,效率比较慢,更新也很慢,要进行数组复制,如果追求读更新高效率可以用hashset,但是hashset元素不允许重复