ArrayList原理

本文详细介绍了Java中ArrayList类的实现原理,包括其数据结构、线程安全问题及解决方案、继承关系、扩容机制以及基本方法如set、get、indexOf、remove和add的具体实现。

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

一、 数据代码结构----跟链表(LinkList)是不同的结构

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    // 版本号
    private static final long serialVersionUID = 8683452581122892189L;
    // 缺省容量
    private static final int DEFAULT_CAPACITY = 10;
    // 空对象数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
    // 缺省空对象数组 
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    // 元素数组
    transient Object[] elementData;
    // 实际元素大小,默认为0
    private int size;
    // 最大数组容量
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    /**
     * 无参构造方法
     * 亲自尝试 List<T> list=new ArrayList<>() 时会走这,构造【缺省空对象数组】
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }




    /**
     * 带参数的构造方法
     * 亲自尝试 List<T> list=new ArrayList<>(7) 时会走这
     */
    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);
        }
    }




   /**
     * Collection<T>类型构造方法
     * 亲自尝试 Collection<MyClass> myCollection; 
     *         ArrayList<MyClass> myList = new ArrayList<MyClass>(myCollection); 
     * 时会走这,但这种构造方法不常用
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

}

二、线程安全

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

第一步:先在object[size]的位置上存放需要添加的元素;

第二步:将size的值增加1。

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

如果非要在多线程的环境下使用ArrayList,就需要保证它的线程安全性,通常有两种解决办法:第一,使用synchronized关键字;第二,可以用Collections类中的静态方法synchronizedList();  对ArrayList进行调用即可。三,CopyOnWriteArrayList这是一个ArrayList的线程安全的变体;

List<String> list = Collections.synchronizedList(new ArrayList<String>());
list.add("1");
list.add("2");
list.add("3");

synchronized (list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext()) {
        //foo(i.next());
        System.out.println(i.next());
    }
}

三、继承关系

ArrayList 继承 AbstractList抽象父类,实现了List接口(规定了List的操作规范)、RandomAccess(可随机访问)、Cloneable(可拷贝)、Serializable(可序列化)

四、扩容机制

add() ----> ensureCapacityInternal(确保内部容量) ----> ensureExplicitCapacity(确保明确的容量) ----> grow(增长) ----> hugeCapacity(若超过最大,返回最大)

五、set 方法,get 方法,index of 方法,remove 方法,add方法(看上面)

set:1. 先判断索引是否合法;2. 如果所引致合法,将索引对应的oldValue取出;3. 将索引指向 newValue;4. 返回oldValue;

get: 1. 判断索引是否合法; 2. 如果所引致合法,则调用elementData(int index)方法获取值

remove:1.判断索引是否合法;2. 将指定下标后面一位到数组末尾的全部元素向前移动一个单位,并且把数组最后一个元素设置为null;

这样方便之后将整个数组不再使用时,会被GC,可以作为小技巧。而需要移动的元素个数为:size-index-1。

String[] s1 = {"中国","山西","太原","TYUT","zyy","加拿大","不知道哪个州","不知道哪个市","不知道哪个学校","yxf"};  
String[] s2 = new String[10];  
System.arraycopy(s1, 1, s2, 0, 8);  把s1集合从下标1开始进行拷贝,拷贝到s2集合里index位置,拷贝的数据长度为8;

indexOf:从头开始查找与指定元素相等的元素,如果找到,则返回找到的元素在元素数组中的下标,如果没有找到返回-1;

1. 判断查找的元素是否为空;   2. 不为空直接循环遍历元素数组,通过equals方法来判断对象是否相同,相同就返回下标,找不到就返回-1;

判断空对象的原因是:若为空调用equals方法则会产生空指针异常

复制数组另一方法:Arrays.copyOf(array, to_index);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值