数据结构(一)ArrayList

数组

数组示意图.jpg

相信大家对数组都很熟悉,但是数组有一个很大的弊端,容量是固定的
因此在不确定数据数量的场景使用起来会很不方便:声明大了浪费空间,声明小了数据存不下。

那么是否可以变更它的存储空间呢?

ArrayList

假设数组的基础长度是3,当想要插入第4个元素(array[3])时,可以考虑这样的算法:
1、重新申请一块连续的空间,空间大小为5。
2、将原来的数据依次复制到新的数组中
3、将第4个元素插入新数组相应的位置

这样,我们便可以摆脱数据长度的限制,放心的使用。ArrayList便是基于这种算法实现的。

ArrayList示意图.jpg

ArrayList源码分析(JDK1.8)

1、ArrayList中存放元素的数组elementData,记录元素个数的变量size

    /**
     * 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.
     */
    // Android-note: Also accessed from java.util.Collections
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

2、扩容方案:
调用链:add() -> ensureCapacityInternal() -> ensureExplicitCapacity() -> grow()

/**
     * 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;
        // 计算新的容量 = 老容量 + 老容量/2
        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);
    }

3、向指定位置添加元素

/**
     * Inserts the specified element at the specified position in this
     * list. Shifts the element currently at that position (if any) and
     * any subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        
        // 判断是否需要扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 从index起,将元素向后移动一位
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        // 给index元素赋值
        elementData[index] = element;
        size++;
    }

4、查询

        public E get(int index) {
            if (index < 0 || index >= this.size)
              throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            if (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
            return (E) ArrayList.this.elementData[offset + index];
        }

其他

1、由于ArrayList基于数组,所以查询效率相对较高,任何位置的元素查询效率一样
2、由于插入元素可能涉及到扩容、复制元素等操作,导致增加、删除元素会有时间损耗

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值