2.20关于JAVA集合点点滴滴重点回顾(ArrayList)

1、ArrayList的使用
demo:

//创建一个ArrayList数组
List<String> list = new ArrayList<>();

//向ArrayList数组中添加元素
list.add("Test");
list.add("test");
System.out.println(list);
//输出["Test","test"]

//获取ArrayList中的元素
list.get(index);

//删除ArrayList中的元素
list.remove();

//....


2、ArrayList的继承体系

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
  //.....
}

从 继承图 和 源码 中我们能看见 ArrayList 实现了 List、RandomAccess、Cloneable、Serializable 等。

实现了 List 可以表明 ArrayList 具有增删改查和遍历等操作。
实现了 RandomAccess 表明 ArrayList 具有随机访问等能力。
实现了 Cloneable 表明 ArrayList 可以被 浅拷贝 。
实现了 Serializable 表明 ArrayList 可以被序列化。

3.扩容机制源码:

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 判断是否需要扩容
        elementData[size++] = e;
        return true;
    }


    private static int calculateCapacity(Object[] elementData, int minCapacity) {
       // 判断当前数组是否是默认构造方法生成的空数组,如果是的话minCapacity=10反之则根据原来的值传入下一个方法去完成下一步的扩容判断
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, 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
     */
		// ArrayList数组中最大的值为Integer的最大值- 8
    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;
      	// 把当前的数组长度扩展为之前的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
      	// 进行判断,如果扩容后还是小于所需长度,则把扩容长度变为最小长度。
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
      	// 如果所需最小扩容长度大于ArrayList中最大的长度
        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) {
      	// 如果越界,则抛出 OutOfMemoryError 异常
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
      	// 判断如果最小值在 Integer.MAX_VALUE - 8 到 Integer.MAX_VALUE 范围就直接使用其中的范围值。
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }


通过上述 流程图 和 源码 的结合,我们能发现一下核心点:

int newCapacity = oldCapacity + (oldCapacity >> 1); 扩容的计算方式。一看是 1.5 倍,其实是不完全正确的。因为oldCapacity >> 1必须是整数。

比如:第一次扩容:应该是 0 + 0/2 = 0 ,

然后通过 if (newCapacity - minCapacity < 0) newCapacity =
minCapacity;将默认值10 赋值给newCapacity。所以无参构造第一次扩容到10。

第二次扩容:是 10 + 10/2 = 15;

第三次扩容: 15 +15/2 = 22; 注意15/2 = 7 ,不是7.5。

通过第三步扩容可以得知,扩容倍数不是1.5倍。实际上是 a = a+a/2。当a 为偶数时,才是1.5倍。

所以所说,只能是 约等于1.5倍 。

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);} 判断当前数组是否是默认构造方法生成的空数组,如果是的话minCapacity=10反之则根据原来的值传入下一个方法去完成下一步的扩容判断。

4、ArrayList常见面试题
4.1、 ArrayList的扩容机制是什么样子的?

4.2、 ArrayList是线程安全的吗?

4.3、 ArrayList 和 LinkedList 的区别?

4.4、 ArrayList 如何解决频繁扩容带来的效率问题?

4.5、 ArrayList插入或删除元素是否一定比LinkedList慢?

4.6、 如何复制某个ArrayList到另外一个ArrayList中去呢?你能列举几种?

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值