ArrayList扩容机制以及线程安全性

ArrayList扩容机制以及线程安全性List扩容实现步骤总的来说就是分两步:1、扩容​ 把原来的数组复制到另一个内存空间更大的数组中2、添加元素​ 把新元素添加到扩容以后的数组中性能分析ArrayList作为动态数组,其内部元素以数组形式顺序存储的,所以非常适合随机访问的场合。除了尾部插入和删除元素,往往性能会相对较差,比如我们在中间位置插入一个元素,需要移动后续所有元素。源码分析先把ArrayList中定义的…

大家好,又见面了,我是你们的朋友全栈君。

List扩容实现步骤

总的来说就是分两步:

1、扩容

​ 把原来的数组复制到另一个内存空间更大的数组中

2、添加元素

​ 把新元素添加到扩容以后的数组中

性能分析

ArrayList作为动态数组,其内部元素以数组形式顺序存储的,所以非常适合随机访问的场合。除了尾部插入和删除元素,往往性能会相对较差,比如我们在中间位置插入一个元素,需要移动后续所有元素。

源码分析

先把ArrayList中定义的一些属性贴出来方便下面源码分析
在这里插入图片描述

ArrayList的两个构造方法

1.ArrayList()
2.ArrayList(int initialCapacity)

无参构造:
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
带参构造:
    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);
        }
    }

在无参构造中,创建了一个空数组,长度为0

在有参构造中,传入的参数是正整数就按照传入的参数来确定创建数组的大小,否则异常

扩容的方法

插入元素函数 (boolean add(E e))

ArrayList在执行插入元素是超过当前数组预定义的最大值时,数组需要扩容,扩容过程需要调用底层System.arraycopy()方法进行大量的数组复制操作。

贴上源码
在这里插入图片描述

public boolean add(E e) { 

	ensureCapacityInternal(size + 1); // Increments modCount!! 

	elementData[size++] = e; 

	return true;

}

看,其实add方法就两步,

第一步:增加长度

第二步:添加元素到数组

ensureCapacityInternal(int minCapacity)这个增加长度的方法

在这里插入图片描述

这个地方我们看到了,如果在添加的时候远数组是空的,就直接给一个10的长度,否则的话就加一

ensureExplicitCapacity(int minCapacity)

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

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

通过这个地方是真正的增加长度,当需要的长度大于原来数组长度的时候就需要扩容了,相反的则不需要扩容
在这里插入图片描述

这个地方注意

int newCapacity = oldCapacity + (oldCapacity >> 1);

oldCapacity >> 1 右移运算符 原来长度的一半 再加上原长度也就是每次扩容是原来的1.5倍

之前的所有都是确定新数组的长度,确定之后就是把老数组copy到新数组中,这样数组的扩容就结束了

以上的一切都是ArrayList扩容的第一步,第二步就没啥说的了,就是把需要添加的元素添加到数组的最后一位

ArrayList安全性

非线程安全

1.在 add 的扩容的时候会有线程安全问题, ensureCapacityInternal(int minCapacity)这个步骤是有线程安全问题

2.在add 的elementData[size++] = e 这段代码在多线程的时候同样会有线程安全问题,

这里可以分成两个步骤:

elementData[size] = e;

size = size + 1;

如果大家对java架构相关感兴趣,可以关注下面公众号,会持续更新java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达, 超神之路从此展开, BTAJ不再是梦想!

架构殿堂

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/131442.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月12日 上午11:46
下一篇 2022年6月12日 上午11:46


相关推荐

  • JPA:@Modifying注解(UPDATE或者DELETE)

    JPA:@Modifying注解(UPDATE或者DELETE)通过 Modifying 注解可以完成修改 UPDATE 或者 DELETE 操作 注意 不支持新增 示例 packagecom newcapec dao repository pay importcom newcapec dao domain UserEnroll importorg springframew data jpa repository JpaRe

    2025年9月6日
    3
  • 求三角形垂心重心

    求三角形垂心重心求垂心 三条垂直平分线的交点 重心 三条中线的交点 交点坐标为三个点坐标之和 3 include include include include includeusing structpoint doublex y p0 p1 p2 ret intTest pointorthoce poin

    2026年3月19日
    2
  • mysql新增字段语句

    mysql新增字段语句ALTERTABLEta nameADDCOLUM nameVARCHAR 100 DEFAULTNULLC 新加字段 AFTERold column 语句内容 table name 表明 column name 需要添加的字段名 VARCHAR 100 字段类型为 varchar 长度 100 DEFAULTNULL 默认值 NULL AFTERold column 新增字段添加在 old column

    2026年3月19日
    3
  • ora01017 linux,ORA-01017: invalid username/password; logon denied 解决办法

    ora01017 linux,ORA-01017: invalid username/password; logon denied 解决办法ORA-01017:invalidusername/password;logondenied解决办法环境介绍:操作系统RHEL6.4X64、数据库:ORACLE11.2.0.4.0;在现有环境下手动创建数据库,在数据库的手动创建过程中没有大的问题,但在数据库创建完成后出现在本地可以登录数据库用户包括管理员账户,通过客户端远端无法登录报如下错误:通过测试,或者在数据库系统中更换用户账户口…

    2022年5月6日
    276
  • jQuery.parseJSON(json)方法将字符串转换成js对象

    jQuery.parseJSON(json)方法将字符串转换成js对象

    2021年8月12日
    81
  • sql prompt工具

    sql prompt工具SQLPrompt是一款拥有SQL智能提示功能和格式化Sql代码插件。可用于的SQLServer和VS。SQLPrompt能根据数据库的对象名称,语法和用户编写的代码片段自动进行检索,智能的为

    2022年7月1日
    35

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号