Java集合之ArrayList

本文深入探讨了Java中ArrayList的数据结构及其实现原理,包括数组扩容机制、添加与删除操作的细节,以及集合操作如removeAll和retainAll的具体实现。

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

 ArrayList底层数据结构是数组,能够高效的在指定位置上进行查找、修改,但是对于插入操作效率不是很高。如果向列表末尾插入元素,当底层数组容量不足以容纳时,需要进行扩容操作。当在指定位置插入时,需要将指定位置以及之后的元素往后移动,腾出位置给新加入的元素。





底层数据结构:


private static final int DEFAULT_CAPACITY = 10; // 默认容量是10,在第一次添加元素时新建数组
/**
 * DEFAULTCAPACITY_EMPTY_ELEMENTDATA和EMPTY_ELEMENTDATA区别:
 * DEFAULT_CAPACITY:表明当前集合容量就是0
 * DEFAULTCAPACITY_EMPTY_ELEMENTDATA:表明当前集合尚未添加元素,而容量为默认容量10,
 * 数组新建发生在第一次加入元素时(加入第一个元素之前暂不新建数组)。
 */
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // elementData中保存的就是集合中元素
private int size; // 当前集合中元素个数


构造方法:


public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) { // 立刻新建数组
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) { // 指定容量为零,数组指定为:EMPTY_ELEMENTDATA
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

public ArrayList() { 
    // 默认容量为10,而在添加第一个元素之前,
    // 数组指定为:DEFAULTCAPACITY_EMPTY_ELEMENTDATA
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

// 根据另一个集合中的所有元素构建新List,元素都是相同的。
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;
    }
}


数组扩容:


private void ensureCapacityInternal(int minCapacity) {
    // 说明是默认容量,尚未添加任何元素,令minCapacity
    // 最小为DEFAULT_CAPACITY(10)
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++; // 集合结构变化次数,定义在父类AbstractList中

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

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

// 扩容机制为:新建一个容量为当前数组容量 1.5 倍的新数组,
// 将当前数组中元素全部拷贝到新数组中
private void grow(int minCapacity) {
    int oldCapacity = elementData.length; // 原数组最大容量
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 右移一位相当于除以2
    if (newCapacity - minCapacity < 0) // 最小扩容到minCapacity
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity); // 数组元素拷贝
}


添加元素操作:


public E set(int index, E element) { // 替换集合某个位置上元素,返回旧元素
    rangeCheck(index); // // 检查index值是否合法

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

public boolean add(E e) { // 向集合中添加元素(末尾)
    ensureCapacityInternal(size + 1);  // 如果当前数组容量不足,需要进行数组扩容
    elementData[size++] = e;
    return true;
}


/**
 * 向指定位置插入元素,此位置以及之后元素顺次后移
 * index的值在 0 和 size 值之间
 */
public void add(int index, E element) {
    rangeCheckForAdd(index); // 检查index值是否合法

    ensureCapacityInternal(size + 1);  // 如果当前数组容量不足,需要进行数组扩容
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index); // 此方法完成数组元素移动
    elementData[index] = element; // 插入元素
    size++;
}


集合操作(removeAll、retailAll):


/**
 * 从当前集合中删除这样的元素:此元素存同时在集合c中,集合减操作
 * 如:{1, 2, 3, 4} - {3, 4, 5} = {1, 2}
 */
public boolean removeAll(Collection<?> c) { 
    Objects.requireNonNull(c);
    return batchRemove(c, false);
}

/**
 * 从当前集合删除这样的元素:此元素不存在集合c中,集合交操作
 * 如:{1, 2, 3, 4} ∩ {3, 4, 5} = {3, 4}
 */
public boolean retainAll(Collection<?> c) {
    Objects.requireNonNull(c);
    return batchRemove(c, true);
}

/**
 * 集合批量删除算法
 */
private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    int r = 0, w = 0;
    boolean modified = false;
    try {
        for (; r < size; r++)
            if (c.contains(elementData[r]) == complement) // 包含或不包含
                elementData[w++] = elementData[r]; // 符合条件元素向前移动,不符合的会被覆盖
    } finally {
        if (r != size) { // contains发生异常,某个元素不符合集合c类型
            System.arraycopy(elementData, r,
                             elementData, w,
                             size - r); // 将集合中剩余未比较的元素以w为起始位置加入
            w += size - r; // 更新w值
        }
        if (w != size) { // 说明存在元素被删除
            for (int i = w; i < size; i++)
                elementData[i] = null; // 数组剩余位置设为null
            modCount += size - w;
            size = w; // 更新集合size
            modified = true;
        }
    }
    return modified;
}

import java.util.ArrayList;
import java.util.List;

public class ArrayListDemo {
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);
        list1.add(4);
        List<Integer> list2 = new ArrayList<>();
        list2.add(1);
        list2.add(2);
        list2.add(3);
        list2.add(4);
        List<Integer> list3 = new ArrayList<>();
        list3.add(3);
        list3.add(4);
        list3.add(5);
        System.out.println(list1.removeAll(list3)); // true
        System.out.println(list2.retainAll(list3)); // true
        System.out.println(list1); // [1, 2]
        System.out.println(list2); // [3, 4]
    }
}


其他一些实用方法(replaceAll、sort、removeIf):


import java.util.ArrayList;
import java.util.List;
import java.util.function.UnaryOperator;

public class ArrayListDemo {
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);
//        list1.replaceAll(integer -> integer * integer); // Lambda
        list1.replaceAll(new UnaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return integer * integer;
            }
        });
        System.out.println(list1); // [1, 4, 9]
    }
}


import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class ArrayListDemo {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(2);
        list.add(3);
        list.add(1);
        list.sort(Comparator.comparingInt(value -> value));
        System.out.println(list); // [1, 2, 3]
        list.sort(Comparator.comparingInt(value -> -value));
        System.out.println(list); // [3, 2, 1]
    }
}


import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class ArrayListDemo {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        // list.removeIf(integer -> integer % 2 == 0); // Lambda
        list.removeIf(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer % 2 == 0;
            }
        });
        System.out.println(list); // [1, 3]
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值