ArrayList扩容机制
admin
2024-03-05 15:06:14
0

ArrayList源码:

首先,新增一个元素时,会调用ensureCapacityInternal函数,传入当前需要的大小,确定是否需要扩容。

    /*** Appends the specified element to the end of this list.** @param e element to be appended to this list* @return true (as specified by {@link Collection#add})*/public boolean add(E e) {ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;return true;}

size是成员变量,默认为0

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

然后调用calculateCapacity确定当前需要的最小容量,调用ensureExplicitCapacity进行扩容

    private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}
    private static int calculateCapacity(Object[] elementData, int minCapacity) {// 如果还没有扩容过,获取DEFAULT_CAPACITY(默认值10)与minCapacity的最大值if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}

modCount为AbstractList的成员变量,为扩容的次数

1.当我们要 add 进第 1 个元素到 ArrayList 时,elementData.length 为 0 (因为还是一个空的 list),因为执行了 ensureCapacityInternal() 方法 ,所以 minCapacity 此时为 10。此时,minCapacity - elementData.length > 0 成立,所以会进入 grow(minCapacity) 方法。

2.当 add 第 2 个元素时,已经扩容过了,calculateCapacity直接返回minCapacity ,也就是 2。

此时 elementData.length(容量)在添加第一个元素后扩容成 10 了。此时,minCapacity - elementData.length > 0 不成立,所以不会进入 (执行)grow(minCapacity) 方法。

    private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious code// 如果第一次list的长度没有指定,minCapacity将为10// 初始化时,elementData.length默认为0,第一次添加元素就会扩容   if (minCapacity - elementData.length > 0)grow(minCapacity);}

进入核心函数grow():

private void grow(int minCapacity) {// oldCapacity为旧容量,newCapacity为新容量int oldCapacity = elementData.length;//将oldCapacity 右移一位,其效果相当于oldCapacity /2,//我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,int newCapacity = oldCapacity + (oldCapacity >> 1);//然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) `hugeCapacity()` 方法来比较 minCapacity 和 MAX_ARRAY_SIZE,//如果minCapacity大于最大容量,则新容量则为`Integer.MAX_VALUE`,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 `Integer.MAX_VALUE - 8`。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);}

注意,如果容量为奇数,右移一位会把小数丢掉,11+11/2 = 21

最后进入Arrays.copyOf()方法:

    public static  T[] copyOf(U[] original, int newLength, Class newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;}

这里 主要是创建了一个我们需要的容量的数组copy,然后把原数组的值辅助到copy中,再返回

进入System.arraycopy()方法:

    /***   复制数组* @param src 源数组* @param srcPos 源数组中的起始位置* @param dest 目标数组* @param destPos 目标数组中的起始位置* @param length 要复制的数组元素的数量,所以传入的是Math.min(original.length, newLength)*/public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

相关内容

热门资讯

数百亲友送别高善文博士,一代宏... 作者 | 刘银平编辑 | 付影来源 | 独角金融7月11日上午,北京的天气阴沉沉的,预报中的大雨始终...
广州市投资发展委员会办公室专职... 广州是一座善于创造奇迹的城市,也是始终向未来敞开大门的城市。《中国企业家》记者 闫俊文见习编辑|李原...
匈牙利大转向?欧尔班的屁股还没... 匈牙利的脸,说变就变了!欧尔班下台才刚3个月,新政府就要拿中国企业立威了?第一个挨刀的,是中国电池隔...
A股265家公司中报归母净利润... 本文来源:时代周报 作者:赵鹏来源:图虫2026年第二季度收官,A股上市公司中报业绩预告陆续发布,券...
佳缘科技遭立案!董事长半年前才... 让子弹飞。作者 | 方璐编辑丨高岩来源 | 野马财经提起佳缘科技(301117.SZ),从公司名称上...
3季度A股主线 3季度A股主线... 从技术指标角度来看,A股周五反包的长阴线很吓人,但都没有跌破新低,如果下周三大估值能收复60日均线,...
【活动回顾】匠心古井传农耕 空... 匠心古井传农耕 空气探秘悟科学 为丰富青少年暑期生活,搭建传统文化与现代科学的交融桥梁,7月11日下...
中国电影市场单日票房突破3亿元... 7月11日消息,网络平台数据显示,截至今日20时34分,中国电影市场单日票房突破3亿元,系今年2月2...
主权财富基金成AI领域重要资金... 7月11日消息,据路透社报道,西班牙IE大学7月10日发布的最新研究报告显示,随着全球地缘政治联盟格...
上海地铁:7月12日运营开始起... 7月11日消息,受今年第9号台风“巴威”影响,上海地铁发布运营调整:7月12日运营开始起,3号线、浦...