ArrayList详解

ArrayList类和它的常见方法

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{// 继承AbstractList类,实现List接口和Serializable序列话接口

    private static final int DEFAULT_CAPACITY = 10; //初始大小,也就是集合的容量
    transient Object[] elementData; // 元素的存放数组
    private int size; // 实际存放元素的数量

    // 直接获取ArrayList的元素数量
    public int size() {
        return size;
    }
    
    // 判断集合内元素是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    // 集合中是否存在该元素 indexOf方法中循环数组用equals比较元素是否相同相同则返回改元素的下标
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    // 将集合转为数组
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    // 检查下标是否超出数组界限
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    // 通过下标获取元素
    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }

    // 修改指定下标的值为element算做替换,返回之前的元素值
    public E set(int index, E element) {
        rangeCheck(index);

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

    // 添加新元素
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

    // 插入添加,把元素添加到指定的下标,之后的下标开始后的元素向后移一位
    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

    // 通过下标移除元素
    public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

    // 移除集合o元素
    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    // 移除集合第一个元素
    // 清空集合
    // 合并集合
    ...

}

 

实例ArrayList

ArrayList<String> arr = new ArrayList<>();// 只能放String类型对象,在添加第一个值的时候初始容量为10

ArrayList arr = new ArrayList<>();// 可以放任意类型Object

ArrayList<String> arr = new ArrayList<>(5);// 限制集合的类型,并设置集合的初始容量5

通过反射获取集合内存放元素的数组

        Class<? extends List> aClass = arr.getClass();
        Field elementData = aClass.getDeclaredField("elementData");
        elementData.setAccessible(true);
        Object[] o = (Object[]) elementData.get(arr);
        System.out.println(o.length);// 数组的长度也就是集合的容量

第一种方式创建的集合输出为0(说明在没有设置集合长度和添加元素的时候集合的长度为零

当给集合添加第一个值后(数组的长度变成了10

arr.add("arr");

当元素增加到11为时数组的长度再次发生变化

当元素增加到16时数组长度又发生了变化

三次变化可以得到一个结论:在元素超过当前数组的长度时,会有一个新的数组替换原来的数组。而新数组的长度为原数组长度加原数组长度的1/2.

那么这么判断是新的数组呢?

通过获取这个数组的hashcode值来判断集合中数组长度变化前和变化后的是否一致

posted @ 2020-09-27 15:51  余光都是你  阅读(102)  评论(0)    收藏  举报