💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### ArrayList * ArrayList类支持能够按需增长的动态数组,增长策略oldCapacity + \(oldCapacity &gt;&gt; 1\)即原来的长度+原长度的一半 ``` int newCapacity = oldCapacity + (oldCapacity >> 1); ``` * 默认容量大小是10 ``` private static final int DEFAULT_CAPACITY = 10; ``` ### 主要API * **add\(E e\)** add主要的执行逻辑如下: 1)确保数组已使用长度(size)加1之后足够存下下一个数据 2)修改次数modCount 标识自增1,如果当前数组已使用长度(size)加1后的大于当前的数组长度,则调用grow方法,增长数组,grow方法会将当前数组的长度变为原来容量的1.5倍。 ``` private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } ``` 3)确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。 4)返回添加成功布尔值; ``` public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } ``` * **add\(int index, E element\)** ![](../assets/20180411104349001.png) 这个方法其实和上面的add类似,该方法可以按照元素的位置,指定位置插入元素,具体的执行逻辑如下: 1)确保数插入的位置小于等于当前数组长度,并且不小于0,否则抛出异常 2)确保数组已使用长度(size)加1之后足够存下下一个数据 3)修改次数modCount标识自增1,如果当前数组已使用长度(size)加1后的大于当前的数组长度,则调用grow方法,增长数组 4)grow方法会将当前数组的长度变为原来容量的1.5倍。 5)确保有足够的容量之后,使用System.arraycopy 将需要插入的位置(index)后面的元素统统往后移动一位。 6)将新的数据内容存放到数组的指定位置(index)上 * grow\(\)扩容 ``` 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); } ``` * **get\(int index\)** ``` public E get(int index) { rangeCheck(index); return elementData(index); } ``` * **remove\(int index\)** 根据索引remove 1)判断索引有没有越界 2)自增修改次数 3)将指定位置(index)上的元素保存到oldValue 4)将指定位置(index)后的元素都往前移动一位 5)将最后面的一个元素置空,好让垃圾回收器回收 6)将原来的值oldValue返回 ``` public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); 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 return oldValue; } ``` _**注意:调用remove方法不会缩减数组的长度,只是将最后一个数组元素置空而已**_ * trimToSize\(\)缩小集合容量 * toArray\(\)将集合转换为数组 * Arrays初始化 ``` List list = Arrays.asList("a", "b"); List list = new ArrayList(){}; ``` ### 知识点 * ArrayList自己实现了序列化和反序列化的方法,因为它自己实现了 private void writeObject\(java.io.ObjectOutputStream s\)和 private void readObject\(java.io.ObjectInputStream s\) 方法 * ArrayList基于数组方式实现,无容量的限制(会扩容) * 添加元素时可能要扩容(所以最好预判一下),删除元素时不会减少容量(若希望减少容量,trimToSize\(\)),删除元素时,将删除掉的位置元素置为null,下次gc就会回收这些元素所占的内存空间。添加删除某个索引的数据时,需要整体移动数组所以效率比较低 * 线程不安全 * add\(int index, E element\):添加元素到数组中指定位置的时候,需要将该位置及其后边所有的元素都整块向后复制一位 * get\(int index\):获取指定位置上的元素时,可以通过索引直接获取(O\(1\)) * remove\(Object o\)需要遍历数组 * remove\(int index\)不需要遍历数组,只需判断index是否符合条件即可,效率比remove\(Object o\)高 * contains\(E\)需要遍历数组 * 使用iterator遍历可能会引发多线程异常 * 中文排序 ``` Collator collator = Collator.getInstance(Locale.CHINA); List list = Arrays.asList("罗友宝", "黄慧", "阿伟", "车晓"); Collections.sort(list, collator); list.stream().forEach(System.err::println); ```