ArrayList Source Code

ArrayList Source Code

说明

承了RanddomAccess —->遍历的话用for最好

elementData是数组 所以在顺序插入和随机访问的情况下使用这个最好

list可以放入重复的值

构造方法

​ 先将继承集合接口Collection的C(如hashset)转化为数组 如果数组长度不是0 而且对象不是Object[] (elementData类型)则将转成Object[]

 public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

方法

trimToSize()

public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

说明:

Trims the capacity of this ArrayList instance to be the list’s current size. An application can use this operation to minimize the storage of an ArrayList instance.

将ArrayList实例的容量 变为list的当前大小 . 应用可以使用这个操作最小化ArrayList实例的存储

获取ArrayList的元素个数是用size. 而length是ArrayList申请的容量大小. 便于不用每次增加的时候都去进行扩容操作.在isEmpty()方法里判断是否为null的时候 直接用size==0判断

modCount是什么? The number of times this list has been structurally modified

这个字段主要防止多线程操作的情况下 ArrayList发生结构性的变化. 例如一个线程正在遍历 而另一个线程正在remove. 在遍历的过程中 会发现某个元素为null 这时 modCount 会告诉迭代器 让其抛出ConcurrentModificationException.如果没有这一个变量,那么系统肯定会报异常ArrayIndexOutOfBoundsException,这样的异常显然不是应该出现的(这些运行时错误都是使用者的逻辑错误导致的,我们的JDK那么高端,不会出现使用错误,我们只抛出使用者造成的错误,而这个错误是设计者应该考虑的),为了避免出现这样的异常,定义了检查。—从这里也可以看出 ArrayList是非线程安全的

参考知乎:https://www.zhihu.com/question/24086463/answer/64717159

add()

说明:Appends the specified element to the end of this list 添加指定元素到list尾部

 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

在 空参初始化的时候 elementData=DFAULTCAPACITY_EMPTY_ELEMENTDATA 然后返回最小容量是默认容量 10 还是size+1 .然后确定明确的容量ensureExplicitCapacity 如果大于10 则扩容 grow

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 再判断一下新数组的容量够不够,够了就直接使用这个长度创建新数组,   
        // 不够就将数组长度设置为需要的长度 
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0) // 判断有没超过最大限制  
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

如何扩容?

看到第二行 就知道 容量变成原来的1.5倍 然后copy到新的数组

更详细的参考:https://blog.csdn.net/wangb_java/article/details/79515302

remove(int index)

说明 Removes the element at the specified position in this list Shifts any subsequent elements to the left 移除list指定位置的元素 将之后的所有元素向左转移

 public E remove(int index) {
        rangeCheck(index);//判断是否越界
        modCount++;
        E oldValue = elementData(index);
        int numMoved = size - index - 1;//获取index位置开始到最后一个位置的个数
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved); // 将elementData数组index+1位置开始拷贝到elementData从index开始的空间
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

batchRemove(Collection

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];// 直接将r位置的元素赋值给w位置的元素,w自增  
        } finally {
            //保留与AbstractCollection的行为兼容性 防止抛出异常导致上面r的右移过程没完成 
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }

int indexOf(Object o)

说明:Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
大体意识是 找到指定元素o在list第一次出现的位置. 如果 list中没有o则返回-1.

 public int indexOf(Object o) {
        if (o == null) {//元素o 为null 则得到该数组中第一个元素为null的下标
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

Object clone()

说明:Returns a shallow copy of this ArrayList instance. (The elements themselves are not copied.)
返回ArrayList实例的浅复制 元素本身不被复制

public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }

这个 浅复制深复制 的区别 参考:https://blog.csdn.net/accp_fangjian/article/details/2423252

toString()

说明:这个方法是继承父类AbstractCollection的Object的 toString()方法.
一般 对数组toString()输出的的值没有太大的意义.但是集合的toString()是打印出集合中的内容,就是因为 AbstractCollection

public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();//在不考虑 线程安全的情况下 字符串拼接最好用StringBuilder
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值