- 1.ArrayList可以通过构造⽅法在初始化的时候指定底层数组的⼤⼩
通过⽆参构造⽅法的⽅式ArrayList()初始化,则赋值底层数Object[] elementData为⼀个默认空数组
Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}所以数组容量为0,只有对数据进⾏添
加add时,才分配默认DEFAULT_CAPACITY = 10的初始容量。
他的⽆参构造器和有参构造器,⽆参就是默认⼤⼩,有参会判断参数
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
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);
}
}
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
- 2.数组扩容实现
假如我们现有一个数组默认长度10,现在需要新增一个元素,但是现在数组已经满了,怎么办呢
1)他会重新定义一个长度为10+10/2的长度为15的数组
2)把原数组拷贝到新数组在把指针指向地址改为新地址。
- 3.针对jdk1.7以后变化
jdk1.7以前,new ArrayList();时候会调用this(10),默认容量是10,1.7以后默认是一个空数组,只有第一次add的时候容量才会改成10,也是为了性能的提高。
- 4.ArrayList的默认数组⼤⼩为什么是10?
据说是因为sun的程序员对⼀系列⼴泛使⽤的程序代码进⾏了调研,结果就是10这个⻓度的数组是最常
⽤的最有效率的。也有说就是随便起的⼀个数字,8个12个都没什么区别,只是因为10这个数组⽐较的
圆满⽽已哈哈。
- 5.ArrayList 增删很慢
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
1)在增加元素之前进行了校验ensureCapacityInternal,如果长度满了就扩容。
在扩容时候jdk1.8以后进行了效率提升,采用了位运算,右移一位,其实就是除以2这个操作。
然后就进行了数组拷贝。
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
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);
}
2)至于为什么说效率慢
⽐如在一个长度为10的数组,我需要在index 5的位置去插入⼀个元素A。
那从代码⾥⾯我们可以看到,他复制了⼀个数组,是从index 5的位置开始的,然后把它放在了index
5+1的位置,给我们要新增的元素腾出了位置,然后在index的位置放⼊元素A就完成了新增的操作了,
如果这时候在遇到扩容就更慢了,删除也是类似方式操作。
- 6)ArrayList是线程安全的么?
当然不是那样效率会更低,Vector是线程安全的
如果你不喜欢vector 也可以用Collections.synchronizedList把集合包起来,也可以达到想要的效果,其实原理和vector一样就是给所有的方法加上一层synchronized
List<String> list = Collections.synchronizedList(new ArrayList<String>());
list.add("1");
list.add("2");
list.add("3");