集合运用之在明确场景下,为集合指定初始容量

本文深入剖析了Java中ArrayList集合如何自动管理长度,详细介绍了其默认长度、扩容机制及性能优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

集合基本上面试时面试必问的,我一个同事曾经面试时就被问过集合的默认长度是多少。下面我们就ArrayList集合的长度来说说指定初始容量的事。

List<Persion> list = new ArrayList<Persion>();

相信大部分在使用集合是,都是类似的声明一个集合,然后用add、remove等方法对集合进行操作,而且因为它是自动管理长度的,所以不用我们特别费心超长的问题,这确实是一个非常好的优点,但也有我们必须要注意的事项。下面我以ArrayList为例深入了解下java是如何实现自动长度的动态管理,从add方法开始,代码如下(我的是jdk1.7):

public boolean add(E paramE)
   {
   //扩展长度
    ensureCapacityInternal(this.size + 1);
    //追加元素
     this.elementData[(this.size++)] = paramE;
     return true;
   }

我们知道ArrayList是一个大小可变的,但它在底层使用的是数组存储(也就是elementData变量),而且数组是定长的,要实行动态长度必然要进行长度的扩展,代码如下:

private void ensureCapacityInternal(int paramInt) {
     this.modCount += 1;

     if (paramInt - this.elementData.length > 0)
      grow(paramInt);
   }

   private void grow(int paramInt)
   {
   //上次(原始)定义的数组长度
     int i = this.elementData.length;
     int j = i + (i >> 1);
     if (j - paramInt < 0)
      j = paramInt;
     if (j - 2147483639 > 0) {
       j = hugeCapacity(paramInt);
     }
     this.elementData = Arrays.copyOf(this.elementData, j);
   }

   private static int hugeCapacity(int paramInt) {
     if (paramInt < 0)
       throw new OutOfMemoryError();
     return paramInt > 2147483639 ? 2147483647 : 2147483639;
  }

我们看到新数组的长度计算方法,并不是增加一个元素,elementData 的长度就加1,而是在达到elementData 长度的临界点时,才将elementData 扩容1.5倍(i + (i >> 1))右移1位相当于除以2,这样有什么好处呢?避免了多次调用copyOf方法的性能开销,否则没加一个元素都要扩容一次,那性能将会非常糟糕。
知道了扩容原则,还有一个问题:elementData 的默认长度是多少呢?答案是10,比如new ArrayList(),则elementData 的初始长度是10.代码如下:

//无参构造,通常用的最多的就是这个
public ArrayList()
  {
  //指定数组长度的有参构造
    this(10);
  }
//指定数组长度的有参构造
public ArrayList(int paramInt)
   {
    if (paramInt < 0) {
       throw new IllegalArgumentException("Illegal Capacity: " + paramInt);
     }
     this.elementData = new Object[paramInt];
  }

默认初始化时声明了一个长度为10的数组,在通过add方法增加弟11个元素时,ArrayList类就自动扩展了,新的elementData 数组长度是10+(10>>1),也就是15,可以看出,如果不设置初始容量,系统就按照1.5倍的规则扩容,每次扩容都是一次数组的拷贝,如果数据量很大,这样的拷贝会非常耗费资源,而且效率非常低下。如果我们已经知道一个ArrayList的可能长度,然后对ArrayList设置一个初始容量则可以显著提高系统性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值