目录
一、ArrayList特点
继承了数组的特点:
- 寻址快:查找元素快。
- 删除以及添加效率较低:如果在集合的指定位置添加元素或者删除元素,那么在添加时,该元素添加到那个位置,则这个位置开始及以后的元素在底层数组中的位置就需要依次向后推进;而在中部删除的话就会造成数组中部空缺,从而使得该元素后面的元素需要向前移动进行填充。
总结:因为添加和删除会涉及到元素移动的操作,因此会影响到集合的速度。但是如果是追加到数组的尾部或者删除尾部的元素就不会存在这个问题。
二、JDK1.7
- 在JDK1.7中,使用ArrayList list = new ArrayList()创建List集合时,底层直接创建了长度是10的Object[]数组elementData;
在接下来调用add()方法向集合中添加元素时,如果本次的添加导致底层elementData数组容量不足,则调用 ensureCapacity(int minCapacity) 方法进行扩容。默认情况下,扩容为原来的1.5倍(>>1),同时将原来数组中的所有数据复制到新的数组中。 - 故而,由此得到结论,在开发中,建议使用带参构造器创建List集合:ArrayList list = new ArrayList(int capacity),
预估集合的大小,直接一次到位,避免中间的扩容,提高效率。
三、JDK1.8
- JDK 1.8和1.7中 ArrayList 最明显的区别就是底层数组在JDK1.8中,如果不指定长度,使用无参构造方法ArrayList list = new ArrayList()创建List集合时,底层的Object[] elementData初始化为{}(空的数组),并没有直接创建长度为10的数组;
- 而在第一次调用add()方法时,底层才创建了长度为10的数组,并将本次要添加的元素添加进去(这样做可节省内存消耗,因为在添加元素时数组名将指针指向了新的数组且老数组是一个空数组这样有利于System.gc(),并不会一直占据内存)。
- 后续的添加和扩容操作与JDK1.7无异。
四、总结
JDK1.7中的ArrayList对象的创建,类似于单例中的饿汉式;
而JDK1.8,则类似于单例中的懒汉式。
这么做的好处就是:延迟了数组的创建,节省内存空间。
1.8和1.7的区别,由于都是比较简单的数组实现,可能除了1.8的代码一些细微的优化更好之外,再就是1.8的代码行数比较多之外(1.8有1461行、1.7有1173行),也可能是注释写的比较详细。其主要函数的具体实现相差无几。