面试系列之集合ArrayList(一)
集合是面试八股文之一,我今天开始就慢慢把这个集合类研究研究,主要从一些底层结构、使用方法和特性进行分析,没有太多的分析源码。
1、基本属性:
1 /**
2 * Default initial capacity.
3 * 默认初始容量大小
4 */
5 private static final int DEFAULT_CAPACITY = 10;
6
7 /**
8 * Shared empty array instance used for empty instances.
9 * 空数组实例
10 */
11 private static final Object[] EMPTY_ELEMENTDATA = {};
12
13 /**
14 * Shared empty array instance used for default sized empty instances. We
15 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
16 * first element is added.
17 * 默认容量的空数组实例
18 */
19 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
20
21 /**
22 * The array buffer into which the elements of the ArrayList are stored.
23 * The capacity of the ArrayList is the length of this array buffer. Any
24 * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
25 * will be expanded to DEFAULT_CAPACITY when the first element is added.
26 * 数组元素对象、用于存放list中的元素
27 */
28 transient Object[] elementData; // non-private to simplify nested class access
29
30 /**
31 * The size of the ArrayList (the number of elements it contains).
32 * 添加的元素的数量
33 * @serial
34 */
35 private int size;
2、划重点:
-
-
最小的扩容量是10,也就是第一次添加元素的时候会从0扩到10,直到添加第11个元素时才会调用grow方法,将当前数组扩容至原来的1.5倍。
-
1 arrayList.add( E element);
2 arrayList.add(int index, E element);
3 arrayList.addAll(Collection<? extends E> c);
删除
1 arrayList.remove(Object o);
2 arrayList.remove(int index)
3 arrayList.removeAll(Collection<?> c)
修改
1 arrayList.set(int index, E element)
查询
1 arrayList.get(int index);
清空
1 arrayList.clear();
判断是否存在
1 arrayList.contains(Object o); 2 arrayList.lastIndexOf(Object o);
4、特性:
1、有序、可重复
存入的Arraylsit的元素是有序的,且取出的时候可以按顺序取出,且存入的元素是可以有重复的
2、查找快、添加删除慢
查找快是因为arraylist是动态数组,长度可变,在内存中分配连续的空间,arraylist中的数据在内存中是连续的,查找的时候直接遍历内存就可以。增删慢是因为增加元素的时候,如果触发了扩容机制,则需要对整个数组进行复制,否则就是在数组中间添加删除的话,也会导致后面的元素移动,影响效率。
3、线程不安全
1 public boolean add(E e) { 2 // 校验是否扩容 3 ensureCapacityInternal(size + 1); // Increments modCount!! 4 elementData[size++] = e; 5 // 相当于 elementData[size] = e;size++; 6 return true; 7 }
假设此时size = 1,数组长度为1;
第一就是数据错误的情况,
线程一, elementData[1] = 1;,时间片结束了,需要等待下一个时间片;
线程二, elementData[1] = 2;,时间片结束了,需要等待下一个时间片;
线程一 size++ size = 2
线程二 size++ size = 3
所以 elementData[1] 的原始值别覆盖了,而elementData[2] 的值却赋值给了elementData[1] ,导致elementData[1] 的值不对,elementData[2]的值也不对且为空。
第二就是内存溢出的情况,
线程一,校验容量通过,时间片结束了,需要等待下一个时间片;
线程二,校验容量通过,时间片结束了,需要等待下一个时间片;
线程一,elementData[1] = 1 ,size++ ;( size = 2);
线程二,之前校验容量通过了,所以没有扩容,elementData[2] = 2,此时因为数组长度为1,所以内存溢出。
我了解的大概就这些,也不是很全面,如有不足或者错误,欢迎指教。