ArrayList实现原理及基本方法

ArrayList是开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,擅长随机访问元素,插入和删除较慢

1、ArrayList的数据结构

ArrayList的底层数据结构就是一个数组,数组元素的类型为Object类型,对ArrayList的所有操作底层都是基于数组的。

2、ArrayList是线程不安全的

对ArrayList进行添加元素的操作的时候是分两个步骤进行的:

  1. 先在object[size]的位置上存放需要添加的元素;
  2. size的值增加1。

由于这个过程在多线程的环境下是不能保证具有原子性 的,因此ArrayList在多线程的环境下是线程不安全的。

在单线程运行的情况下,如果Size = 0,添加一个元素后,此元素在位置 0,而且Size=1;而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此ArrayList 添加元素,因为此时 Size 仍然等于 0

注意:我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将 元素存放在位置0。然后线程A和线程B都继续运行,都增 加 Size 的值。 那好,现在我们来看看ArrayList 的情况,元素实际上只有一个,存放在位置 0,而Size却等于 2。这就是“线程不安全”了。

如果非要在多线程的环境下使用ArrayList,就需要保证它的线程安全性,通常有两种解决办法:

  • 使用synchronized关键字;
  • 可以用Collections类中的静态方法synchronizedList(),对ArrayList进行调用即可。

3、ArrayList的实现

对于ArrayList而言,它实现List接口、底层使用数组保存所有元素。其操作基本上是对数组的操作。下面我们来分析ArrayList的源代码:

1) 私有属性:

ArrayList定义只定义类两个私有属性:

/**
*ArrayList 的元素存储在其中的数组缓冲区。
*ArrayList 的容量就是这个数组缓冲区的长度。添加第一个元素时,任何带有 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空 ArrayList 都将扩展为 DEFAULT_CAPACITY(10)。
*/
transient Object[] elementData;

// ArrayList 的大小
private int size;

Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。

有点抽象,看个例子应该能明白:

public class UserInfo implements Serializable {
   
    private static final long serialVersionUID = 996890129747019948L;
    private String name;
    private transient String psw;

    public UserInfo(String name, String psw) {
   
        this.name = name;
        this.psw = psw;
    }

    public String toString() {
   
        return "name=" + name + ", psw=" + psw;
    }
}

public class TestTransient {
   
    public static void main(String[] args) {
   
        UserInfo userInfo = new UserInfo("张三", "123456");
        System.out.println(userInfo);
        try {
   
            // 序列化,被设置为transient的属性没有被序列化
            ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.out"));
            o.writeObject(userInfo);
            o.close();
        } catch (Exception e) {
   
            e.printStackTrace();
        }
        try {
   
            // 重新读取内容
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.out"));
            UserInfo readUserInfo = (UserInfo) in.readObject();
            // 读取后psw的内容为null
            System.out.println(readUserInfo.toString());
        } catch (Exception e) {
   
            e.printStackTrace();
        }
    }
}

被标记为transient的属性在对象被序列化的时候不会被保存。回到ArrayList的分析中

2) 构造方法:

ArrayList提供了三种方式的构造器,可以构造一个默认初始容量为10的空列表、构造一个指定初始容量的空列表以及构造一个包含指定collection的元素的列表,这些元素按照该collection的迭代器返回它们的顺序排列的。

/**
 * 构造一个具有指定初始容量的空列表。
 */
public ArrayList(int initialCapacity) {
   
    if (initialCapacity > 0)
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值