ArrayList优点:随机读性能很高,因为底层是基于数组实现,可以通过get(i)寻址快速读取 获取元素的个数性能很高 arrayLis天生按元素插入顺序排序 ArrayList缺点:在扩容时需要从旧数组把元素拷贝到新数组,性能很差 在随机插入时会导致插入点之后的元素在数组中移动,性能也很差 ArrayList使用场景及使用注意事项:在new ArrayList时最好根据业务场景进行容量的初始化,避免在之后的Add操作时触发数组的扩容,进而提高使用性能 如果有频繁的add(i,e)的操作则不建议使用 ArrayList最好使用在一次性add,之后都是读的场景 ArrayList的元素天生可以重复,所以需要去重的场景不适合 ArrayList主要方法解析:ArrayList构造器:无参构造器:ArrayList(); 构造一个空的数组 ArrayList(int initialCapacity) 按照给定容量大小初始化一个数组 ArrayList(Collection<? extends E> c) 根据给定集合进行初始化数组 使用建议:最好不用使用无参构造器,应该根据业务场景给定容量大小,这样可以避免在后续的add环节频繁的扩容以及新旧数组间的元素拷贝 add(E e)方法:在数组的size+1位置放入元素检查是否需要数组扩容 计算需要的最小容量大小:calculateCapacity方法 如果当前数组是默认的空数组则使用默认容量也就是10,否则就是当前元素size+1 如果计算出来的需要的容量大小大于当前数组大小则需要扩容 扩容:grow(miniCapacity) 新数组长度的计算 数组长度默认是旧数组长度的1.5倍(int newCapacity = oldCapacity + (oldCapacity >> 1); 如果旧数组长度的1.5倍小于miniCapacity,则新数组长度取miniCapacity 如果miniCapacity大于MAX_ARRAY_SIZE长度,则取Integer的最大长度 把旧数组的元素拷贝到新数组中(Arrays.copyOf(elementData, newCapacity)),底层使用的System.ArrayCopy方法 在数组的size+1位置放入e元素elementData[size++] = e; 使用建议:这个方法在ArrayList中是最常用的,在整个过程中可以看出如果使用无参构造器第一次add就会进行数组扩容,初始化容量大小是10,每次扩容以旧容量的1.5倍进行。这个方法的性能瓶颈也就在这个过程中了 add(int index,E e)方法:在数组的index位置放入元素检查index是否超过数组大小,超过则报错 检查是否需要扩容以及需要的话再进行扩容 把index位置及之后的元素都往后移一个位置 在数组index位置上放入e元素 size++ 使用建议:这个方法性能瓶颈在第二步和第三步(扩容和数组元素的移动),所以这个方法不建议使用,而且在真正的生产中也是几乎不用的 addAll(Collection c)方法:把集合c中的元素都加上数组中检查是否需要扩容以及需要的话再进行扩容 通过System.arrayCopy把c中的元素都拷贝到数组中 set(int index,E e)方法:在数组的index位置放入元素检查index是否超过数组大小,超过则报错 拿出index位置的元素,在之后返回 在数组index位置放入元素 使用建议:这个方法非常不常用, 也没有优缺点 get(int index)方法:获取数组的index位置元素 简单不说了 remove(int index)方法:删除数组的index位置元素 通过数组元素的移动覆盖index位置的元素,然后置空s数组ize-1位置达到删除的目的。 remove(Object o)方法:删除数组中指定元素 通过遍历数组找到o元素所在的index,再 通过数组元素的移动覆盖index位置的元素,然后置空s数组ize-1位置达到删除的目的。 iterator()方法:迭代ArrayList中的元素 会new Itr()的一个内部类,通过游标cursor进行遍历,需要注意的是如果在遍历的过程中增加或删除元素会导致报ConcurrentModificationException subList(int fromIndex,int toIndex):生成子List 会new SubList()的一个内部类,这个内部类具有ArrayList中的所有方法,而且所有方法操作的数组还是之前ArrayList中的数组。 欢迎关注"java面试工程师"公众号