0
点赞
收藏
分享

微信扫一扫

java基础:【集合】谈谈 ArrayList 类 #私藏项目实操分享#

m逆光生长 2022-02-26 阅读 56

ArrayList

常量说明

   /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

通过以上可以看出
ArrayList 默认容量值为 10, 默认元素数据为 {}
只有在增加第一个元素的时候,默认容量才会被分配。
这也是减少内存开销的一种方式,我们在日常代码开发中也可加以灵活运用。

元素存储

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

ArrayList 中元素存储在 elementData 数组对象中。且该数组对象是 transient

对象实例化

无参构造

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

案例:


@Test
public void testNoArgCon() {
// 使用无参构造创建对象,此时,
// this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
// 即 this.elementData = {}
List<String> list = new ArrayList<>();
    // Any empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
    // will be expanded to DEFAULT_CAPACITY when the first element is added.
    // 即 先 this.elementData = new Object[10];
    // 此时 ArrayList 容量为 10 ;
    list.add("空列表,增加第一个元素时,分配默认容量");
}

## 指定容量实例化
/**
 * Constructs an empty list with the specified initial capacity.
 *
 * @param  initialCapacity  the initial capacity of the list
 * @throws IllegalArgumentException if the specified initial capacity
 *         is negative
 */
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

## 将其他集合转换实例化
/**
 * Constructs a list containing the elements of the specified
 * collection, in the order they are returned by the collection's
 * iterator.
 *
 * @param c the collection whose elements are to be placed into this list
 * @throws NullPointerException if the specified collection is null
 */
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

# 存储优化
/**
 * Trims the capacity of this <tt>ArrayList</tt> instance to be the
 * list's current size.  An application can use this operation to minimize
 * the storage of an <tt>ArrayList</tt> instance.
 */
public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = (size == 0)
          ? EMPTY_ELEMENTDATA
          : Arrays.copyOf(elementData, size);
    }
}

> 案例:
@Test
public void testTrimToSize() {
    // 使用无参构造创建对象,此时,
    // this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    // 即 this.elementData = {}
    ArrayList<String> list = new ArrayList<>();

    // Any empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
    // will be expanded to DEFAULT_CAPACITY when the first element is added.
    // 即 先 this.elementData = new Object[10];
    // 此时 ArrayList 容量为 10 ;
    list.add("空列表,增加第一个元素时,分配默认容量");

    // 通过该方法整理空间
    // 整理后 ArrayList 容量为 1 ;
    // 相较于整理前 节省了 9个 容量。起到了优化作用
    list.trimToSize();
}
# 扩容
/**
 * Increases the capacity of this <tt>ArrayList</tt> instance, if
 * necessary, to ensure that it can hold at least the number of elements
 * specified by the minimum capacity argument.
 *
 * @param   minCapacity   the desired minimum capacity
 */
public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        // any size if not default element table
        ? 0
        // larger than default for default empty table. It's already
        // supposed to be at default size.
        : DEFAULT_CAPACITY;

    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

/**
 * The maximum size of array to allocate.
 * Some VMs reserve some header words in an array.
 * Attempts to allocate larger arrays may result in
 * OutOfMemoryError: Requested array size exceeds VM limit
 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

/**
 * Increases the capacity to ensure that it can hold at least the
 * number of elements specified by the minimum capacity argument.
 *
 * @param minCapacity the desired minimum capacity
 */
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);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

> 关于扩容过程最好带入几种情况,去跟踪一下,会更加形象地理解整个过程。
> 具体跟踪过程略,感兴趣的同学自己操作下。

---

了解更多 [java基础:目录索引](https://blog.51cto.com/u_14889520/4838367)
举报

相关推荐

0 条评论