ArrayList源码

先介绍几种初始化方法java

// 带初始化容量的初始化
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            // 初始话一个object 数组
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            // 初始话一个空数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            // 抛出错误
            throw new IllegalArgumentException("Illegal Capacity: "+
                    initialCapacity);
        }
    }

    // 默认初始化
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    // 使用一个集合初始化
    public ArrayList(Collection<? extends E> c) {
        // 将集合转化成数组
        elementData = c.toArray();
        // size是arraylist的长度,赋予集合的长度
        if ((size = elementData.length) != 0) {
            // 长度不为0, 集合转化为数组后,若是类型不是object的,转为object
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // 初始化一个空数组
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

重点看下c.toArray方法,假如这个集合是个arraylist类型的,那它的toArray实现以下编程

    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

发现,调用的是Arrays.copyof方法数组

    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

继续看多线程

/**
     *
     * @param original 要复制的数组
     * @param newLength 要复制的长度
     * @param newType 要复制的数组的class类型
     * @param <T>
     * @param <U>
     * @return
     */
    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        // 这步的做用实际上是个优化,假如newType类型是一个object类型,那就直接使用new Object来进行建立数组,加入不是,就用反射的机制建立数组
     // 优化的理由应该是:反射建立数组的性能为比直接建立的性能来的低
// (Object)newType == (Object)Object[].class 这句话就是判断newType是否是一个object类型 // newType.getComponentType() 实际上是得到数组类型,假如说数组是一个String[],那这能够拿到String T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); // 调用本地方法,建立数组 System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }

 再介绍ArrayList两个操做ide

// 移除全部在c集合里的元素
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

    // 保留全部在c集合里的元素
    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 {
            // 根据complement判断是否保留
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            // 假如出现错误,将这个元素后面的全部元素都放到elementData中,不在作去除操做
            if (r != size) {
                System.arraycopy(elementData, r,
                        elementData, w,
                        size - r);
                w += size - r;
            }
            // 若是没出现错误
            if (w != size) {
                // clear to let GC do its work
                // 将被去除的元素置为null
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                // 修改次数
                modCount += size - w;
                // 修改当前数组长度
                size = w;
                // 表示作过修改
                modified = true;
            }
        }
        return modified;
    }

 提下java的迭代器,经过迭代器来操做ArrayList函数

取得迭代器oop

// 返回带指定游标的迭代器ListIterator
    public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }

    // 返回游标默认为0的迭代器ListIterator
    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }

    // 返回默认的迭代器Iterator
    public Iterator<E> iterator() {
        return new Itr();
    }

再看下迭代器的实现性能

Iterator:优化

    private class Itr implements Iterator<E> {
        int cursor;       // 角标,下个元素的位置
        int lastRet = -1; // 上次操做的元素位置
        int expectedModCount = modCount; //用户操做ArrayList,会改变modCount

        public boolean hasNext() {
            return cursor != size; // 角标不为ArrayList长度,则表示有下一个
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification(); // 检查用户是否在操做ArrayList,若是操做不在迭代
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1; // 角标位置+1
            return (E) elementData[lastRet = i]; // 返回当前元素
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification(); // 检查用户是否在操做ArrayList,若是操做不在迭代

            try {
                ArrayList.this.remove(lastRet); // ArrayList移除这个元素
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount; // 从新赋予新的修改次数
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        // 从当前角标的位置,到结束,consumer为函数编程接口,传各个元素进去执行自定义函数,若在操做过程当中,ArrayList发送了修改,则退出迭代,并抛出错误
        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        // 检查当前的ArrayList是否被修改
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

listItrui

    private class ListItr extends Itr implements ListIterator<E> {
        // 角标设为index
        ListItr(int index) {
            super();
            cursor = index;
        }

        // 判断前面是否有元素
        public boolean hasPrevious() {
            return cursor != 0;
        }

        // 返回当前角标,就是下个元素的位置
        public int nextIndex() {
            return cursor;
        }

        // 返回当前元素的位置
        public int previousIndex() {
            return cursor - 1;
        }

        // 返回当前元素,并将角标改成当前元素的位置
        @SuppressWarnings("unchecked")
        public E previous() {
            checkForComodification();
            int i = cursor - 1;
            if (i < 0)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i;
            return (E) elementData[lastRet = i];
        }

        // 设置当前元素的值
        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.set(lastRet, e);
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        // 将值添加到当前元素以后
        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                ArrayList.this.add(i, e);
                cursor = i + 1;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

能够看出迭代器在遍历数组时,同时能够增长删除,角标都会随之发生变化。

而若是用for循环遍历ArrayList进行添加删除操做,若是不对当前位置进行一些控制,将发生一些明显的错误。在多线程的状况,操做ArrayList,你将没法知晓其它线程是否有进行添加删除操做,两方同时操做必将发生错误。

咱们能够看看下面的add操做,它只是作了添加一个元素,并将size+1,而迭代器在添加的时候会进行判断modcount是否发生改变,并将角标自动+1。保证了操做的正确性。

    // 添加 元素
    public boolean add(E e) {
        // 调整容量
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 赋值,并将szie+1
        elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { // 记得前面默认初始化ArrayList的时候,会将elementData赋值为DEFAULTCAPACITY_EMPTY_ELEMENTDATA if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 这时候判断当前的size和DEFAULT_CAPACITY,第一次添加,size为0,因此容量将被初始化为常量10 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { // 修改次数+1,若是迭代器这时候再操做元素,将抛出异常,并中断迭代 modCount++; // 若是minCapacity的容量大于数组中元素的长度 if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; //newCapacity为元素长度的1.5倍 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); }

 

ArrayList中还有个可分割的迭代器

//可分割迭代器
    static final class ArrayListSpliterator<E> implements Spliterator<E> {
        //用于存放ArrayList对象
        private final ArrayList<E> list;
        //起始位置(包含),advance/split操做时会修改
        private int index;
        //结束位置(不包含),-1 表示到最后一个元素
        private int fence;
        //用于存放list的modCount
        private int expectedModCount;

        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                             int expectedModCount) {
            this.list = list;
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }
        //获取结束位置(存在乎义:首次初始化石需对fence和expectedModCount进行赋值)
        private int getFence() {
            int hi;
            ArrayList<E> lst;
            //fence<0时(第一次初始化时,fence才会小于0):
            if ((hi = fence) < 0) {
                //list 为 null时,fence=0
                if ((lst = list) == null)
                    hi = fence = 0;
                else {
                    //不然,fence = list的长度。
                    expectedModCount = lst.modCount;
                    hi = fence = lst.size;
                }
            }
            return hi;
        }
        //分割list,返回一个新分割出的spliterator实例
        // 这里要注意,index已被赋值为mid,起始位置已发生改变
        public ArrayListSpliterator<E> trySplit() {
            //hi为当前的结束位置
            //lo 为起始位置
            //计算中间的位置
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            //当lo>=mid,表示不能在分割,返回null
            //当lo<mid时,可分割,切割(lo,mid)出去,同时更新index=mid
            return (lo >= mid) ? null :
                    new ArrayListSpliterator<E>(list, lo, index = mid,                                         expectedModCount);
        }
        //返回true 时,只表示可能还有元素未处理
        //返回false 时,没有剩余元素处理了。。。
        // 注意index+1,角标向前移动了觉得,下次再调用这个方法就是处理下个元素
        public boolean tryAdvance(Consumer<? super E> action) {
            if (action == null)
                throw new NullPointerException();
            //hi为当前的结束位置
            //i 为起始位置
            int hi = getFence(), i = index;
            //还有剩余元素未处理时
            if (i < hi) {
                //处理i位置,index+1
                index = i + 1;
                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
                action.accept(e);
                //遍历时,结构发生变动,抛错
                if (list.modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                return true;
            }
            return false;
        }
        //顺序遍历处理全部剩下的元素
        //在这个方法里,角标index不发生变化,并处理index到fence里的元素
        public void forEachRemaining(Consumer<? super E> action) {
            int i, hi, mc; // hoist accesses and checks from loop
            ArrayList<E> lst; Object[] a;
            if (action == null)
                throw new NullPointerException();
            if ((lst = list) != null && (a = lst.elementData) != null) {
                //当fence<0时,表示fence和expectedModCount未初始化
                if ((hi = fence) < 0) { /// 注意hi在这里被赋值
                    mc = lst.modCount;
                    hi = lst.size;
                }
                else
                    mc = expectedModCount;
                if ((i = index) >= 0 && (index = hi) <= a.length) {
                    for (; i < hi; ++i) {
                        @SuppressWarnings("unchecked") E e = (E) a[i];
                        //调用action.accept处理元素
                        action.accept(e);
                    }
                    //遍历时发生结构变动时抛出异常
                    if (lst.modCount == mc)
                        return;
                }
            }
            throw new ConcurrentModificationException();
        }

        // 返回剩下元素长度
        public long estimateSize() {
            return (long) (getFence() - index);
        }

        public int characteristics() {
            //打上特征值:、能够返回size
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
        }
    }

 使用下这个ArrayList的可分割迭代器

public static void main(String[] args) throws IOException, ClassNotFoundException {

        List<String>  arrs = new ArrayList<>();
        arrs.add("a");
        arrs.add("b");
        arrs.add("c");
        arrs.add("d");
        arrs.add("e");
        arrs.add("f");
        arrs.add("h");
        arrs.add("i");
        arrs.add("j");

        Spliterator<String> a =  arrs.spliterator();
        //运行到这里,结果:a:0-9(index-fence)

        Spliterator<String> b = a.trySplit();
        //运行到这里,结果:a:4-9 b:0-4

        Spliterator<String> c = a.trySplit();
        //运行到这里,结果:a:6-9 b:0-4 c:4-6
    }

注意,这个分割都是从index到fence,fence通常为迭代器里最大操做位置,index为当前操做的位置,若是操做了第一个元素,好比使用了tryAdvance。那index+1,则分割的时候,也是index到(index+fence)/2;分割出去。

public static void main(String[] args) throws IOException, ClassNotFoundException {

        List<String>  arrs = new ArrayList<>();
        arrs.add("a");
        arrs.add("b");
        arrs.add("c");
        arrs.add("d");
        arrs.add("e");
        arrs.add("f");
        arrs.add("h");
        arrs.add("i");
        arrs.add("j");

        Spliterator<String> a =  arrs.spliterator();
        //运行到这里,结果:a:0-9(index-fence)

        Consumer<String> t = (inputStr) -> {System.out.println(inputStr.equals("a") ? "的确为a":"不是a啊");};
        a.tryAdvance(t);
        //运行到这里,输出:的确为a

        Spliterator<String> b = a.trySplit();
        //运行到这里,结果:a:5-9 b:1-5

        Spliterator<String> c = a.trySplit();
        //运行到这里,结果:a:7-9 b:1-5 c:5-7
    }
相关文章
相关标签/搜索