美文网首页
java集合源码阅读(一) ArrayList

java集合源码阅读(一) ArrayList

作者: 坠叶飘香 | 来源:发表于2019-03-21 15:48 被阅读0次

    1. ArrayList的继承关系

    ArrayList.png

    2.重要属性

    (1)size:实际元素个数
    因为size这个值是时时更新的,通过size() 获取元素个数时,不耗时。
    private int size;
    
    public int size() {
        return size;
    }
    
    (2)elementData:数据容器
    从这里可以看出,ArrayList的数据实际上是存放在一个数组中,所以ArrayList可以快速的获取处于index位的元素
    transient Object[] elementData;
    
    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }
    

    3.add方法

    数组elementData容器的默认大小0,第一次add数据时,会创建一个length为10的elementData;以后的每次add动作一旦发现elementData的length不够放入新的元素,会再次创建一个新的elementData,
    新elementData的length=oldlength +oldlength/2
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    

    4.remove方法

    (1) 通过index删除相应位置的元素:直接执行System.arraycopy
    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);
        }
        //这里不忘把最后一个元素设置为null,让GC可以将它回收
        elementData[--size] = null; // clear to let GC do its work
        return oldValue;
    }
    
    (2) 通过value移除
    • 循环遍历数组,判断每个元素是否与value相等,如果找到一个相等的,执行System.arraycopy
    • 如果存在多个相同的value,只会移除第一个
    • ArrayList元素可以添加null元素
    • null元素与非null需要分开处理
    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;
    }
    

    5.set方法:直接修改数组位于index处的元素

    public E set(int index, E element) {
        rangeCheck(index);
    
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
    

    6.关于使用ListIterator还是for遍历的问题

    两种遍历的不同点主要在获取index处的元素

    从代码上看ListIterator比for多了两次i的检测和一次cursor的求值;在数据量很小的情况下没有什么差别,
    用5000个数据来遍历的话,for的时间为1,ListIterator为2。

    ListIterator:
    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }
    
    for:
    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }
    

    相关文章

      网友评论

          本文标题:java集合源码阅读(一) ArrayList

          本文链接:https://www.haomeiwen.com/subject/xdxcvqtx.html