千家信息网

ArrayList有什么用

发表于:2024-11-17 作者:千家信息网编辑
千家信息网最后更新 2024年11月17日,本篇内容介绍了" ArrayList有什么用"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Array
千家信息网最后更新 2024年11月17日ArrayList有什么用

本篇内容介绍了" ArrayList有什么用"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

ArrayList是一个有序列表。

public class ArrayList extends AbstractList     implements List, RandomAccess, Cloneable, java.io.Serializable
  • RandomAccess 标识接口,无内部方法,表示可以随机访问内部元素

  • Cloneable 标识接口,无内部方法,表示可以进行负责

  • java.io.Serializable 标识接口,无内部方法,表示支持序列化

底层数据结构是一个对象数组

transient Object[] elementData;

ArrayList对象有存储上限

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

缩容,当buffer分配的空间容量大于实际存储的元素数量时,通过缩容释放对于的资源。

public void trimToSize() {    modCount++;    if (size < elementData.length) {        elementData = (size == 0)          ? EMPTY_ELEMENTDATA          : Arrays.copyOf(elementData, size);    }}

扩容,步长为原容量的 50%, 扩容后将原buffer复制到新创建的buffer中。所以ArrayList如果存在频繁扩容的情况,会引起程序性能下降。

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);}

插入或删除指定位置的Element,都会引起底层数据的批量复制

插入

public void add(int index, E element) {        rangeCheckForAdd(index);        ensureCapacityInternal(size + 1);  // Increments modCount!!        System.arraycopy(elementData, index, elementData, index + 1,                         size - index);        elementData[index] = element;        size++;    }

删除

 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;}private void fastRemove(int index) {    modCount++;    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}

清空数据时,并不释放底层数组分配的空间,只是将数组中的对象持有复制成null,方便虚拟机在GC时,直接将对象内存释放。

public void clear() {    modCount++;    // clear to let GC do its work    // 释放句柄,告诉GC对象可以被回收,但并不是立即回收    for (int i = 0; i < size; i++)        elementData[i] = null;    size = 0;}

在数据计算中存在集合求交集运算,在ArrayList中同样提供了该方法。

求交集

public boolean retainAll(Collection c) {    Objects.requireNonNull(c);    return batchRemove(c, true);}private boolean batchRemove(Collection c, boolean complement) {    final Object[] elementData = this.elementData;    int r = 0, w = 0;    boolean modified = false;    try {        for (; r < size; r++)            if (c.contains(elementData[r]) == complement)                elementData[w++] = elementData[r];    } finally {        // Preserve behavioral compatibility with AbstractCollection,        // even if c.contains() throws.        if (r != size) {            System.arraycopy(elementData, r,                             elementData, w,                             size - r);            w += size - r;        }        if (w != size) {            // clear to let GC do its work            for (int i = w; i < size; i++)                elementData[i] = null;            modCount += size - w;            size = w;            modified = true;        }    }    return modified;}

ArrayList实现了Serializable接口,表示它可以被序列化,在其内部提供了jdk标准的序列化和反序列号的方法。通过序列化和发序列化方法可以发现,JDK并不是把ArrayList所有属性都写入文件,只是将size,以及数组中的每一个对象进行了序列化。

private void writeObject(java.io.ObjectOutputStream s)    throws java.io.IOException{    // Write out element count, and any hidden stuff    int expectedModCount = modCount;    s.defaultWriteObject();    // Write out size as capacity for behavioural compatibility with clone()    s.writeInt(size);    // Write out all elements in the proper order.    for (int i=0; i
0