[TOC]

ArrayList

简介

ArrayList实现了List的接口, 是一个顺序存储的容器, 允许放入null元素,底层通过数组实现, 线程非安全.ArrayList有一个capacity表示容量, 如果在向容器中添加元素且容量不足的时候, 容器会自增大底层数组的大小.

源码剖析

成员变量

//默认的初始化容量
private static final int DEFAULT_CAPACITY = 10;
//空表实例的默认元素
private static final Object[] EMPTY_ELEMENTDATA = {};
//空实例的默认大小空数组. 和上面的EMPTY_ELEMENTDATA甲乙区分是为了当添加第一个元素的时扩容多大.
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//存储表对象的数组
transient Object[] elementData;
//表的大小
private int size
//最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

方法分析

//构造函数1
    public ArrayList() {
      //将内部的数组初始化空数组.
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
//构造函数2
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
          //以initialCapacity初始化数组大小
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
          //如果传参为0 则初始化一个空数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
          // 非法草书抛出异常.
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
//构造函数3
//直接使用一个集合初始化一个ArrayList.
    public ArrayList(Collection<? extends E> c) &#123;
        elementData = c.toArray();
        if ((size = elementData.length) != 0) &#123;
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        &#125; else &#123;
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        &#125;
    &#125;
增删改查
扩容相关函数
// 增大容量来容纳指定数量的元素
    private void grow(int minCapacity) &#123;
        // overflow-conscious code
        int oldCapacity = elementData.length;
      //新的数组长度是旧数组长度的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:
      //拷贝数组. 最终调用的是System.arrayCopy
        elementData = Arrays.copyOf(elementData, newCapacity);
    &#125;
    //大容量
    private static int hugeCapacity(int minCapacity) &#123;
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
      //if 大于最大容量 = Integer.MAX_VALUE
      //else 等于最大的数组大小.
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    &#125;

    //
   private void ensureCapacityInternal(int minCapacity) &#123;
     //如果ElementData恒等于默认的空数组.
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) &#123;
          // 取最大的值作为容量.
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        &#125;
                //扩容. 
        ensureExplicitCapacity(minCapacity);
    &#125;
    private void ensureExplicitCapacity(int minCapacity) &#123;
        modCount++; //更改++
                
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
          //如果需求组的容量大于数组的长度, 那么要扩容.
            grow(minCapacity);
    &#125;


    //直接增加.
        public boolean add(E e) &#123;
      //检查容量及扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
      //提那家元素
        elementData[size++] = e;
      //添加成功返回true
        return true;
    &#125;
//插入
//检查范围
    private void rangeCheckForAdd(int index) &#123;
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    &#125;
            
//
        public void add(int index, E element) &#123;
        //检查范围 
        rangeCheckForAdd(index);
                //检查容量
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //拷贝移动数组
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        //向目标位置插入元素
        elementData[index] = element;
        //size自增
        size++;
    &#125;
//将一个集合直接添加到ArrayList
    public boolean addAll(Collection<? extends E> c) &#123;
      //转为数组
        Object[] a = c.toArray();
      //集合的长度
        int numNew = a.length;
      // 检查容量
        ensureCapacityInternal(size + numNew);  // Increments modCount
      //拷贝
        System.arraycopy(a, 0, elementData, size, numNew);
      //size增加numNew
        size += numNew;

        return numNew != 0;
    &#125;

//向指定位置直接插入集合
public boolean addAll(int index, Collection<? extends E> c) &#123;
  // 检查范围
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
  //移动数组
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    &#125;
查找
//指定位置索引
    public E get(int index) &#123;
        rangeCheck(index);

        return elementData(index);
    &#125;
//直接索引第一个可以找到的对象
    public int indexOf(Object o) &#123;
        if (o == null) &#123;
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        &#125; else &#123;
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        &#125;
        return -1;
    &#125;
删除
//直接清除
    public void clear() &#123;
        modCount++;
                //大量的数据并且频繁操作可能引发频繁GC
        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    &#125;
//删除指定位置元素
    public E remove(int index) &#123;
      //范围检查
        rangeCheck(index);
//操作数自增
        modCount++;
      // 保存这个被删除的元素 后续会返回
        E oldValue = elementData(index);
    //  要移动的元素个数
        int numMoved = size - index - 1;
      //移动元素
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
      //尾部的元素置null
        elementData[--size] = null; // clear to let GC do its work
//将被删除的元素返回
        return oldValue;
    &#125;

//删除第一个能找到的指定元素
//快速移除, 不检查边界, 并且不返回被移除的对象.
    private void fastRemove(int index) &#123;
      //修改计数+1;
        modCount++;
      //计算要移动的数量.
        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
    &#125;

public boolean remove(Object o) &#123;
  //如果指定的恒等于null
        if (o == null) &#123;
          //找到这个null元素
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) &#123;
                  //快速移动
                    fastRemove(index);
                    return true;
                &#125;
        &#125; else &#123;
          //找到这个非null元素, 并移除
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) &#123;
                    fastRemove(index);
                    return true;
                &#125;
        &#125;
        return false;
    &#125;

        protected void removeRange(int fromIndex, int toIndex) &#123;
            if (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
            parent.removeRange(parentOffset + fromIndex,
                               parentOffset + toIndex);
            this.modCount = parent.modCount;
            this.size -= toIndex - fromIndex;
        &#125;

//AbstractList
/*
Overriding this method to take advantage of
     * the internals of the list implementation can <i>substantially</i>
     * improve the performance of the &#123;@code clear&#125; operation on this list
     * and its subLists.
     */
    protected void removeRange(int fromIndex, int toIndex) &#123;
        ListIterator<E> it = listIterator(fromIndex);
        for (int i=0, n=toIndex-fromIndex; i<n; i++) &#123;
            it.next();
            it.remove();
        &#125;
    &#125;

//implementation improve the performance
//为什么这个方法是protected 可以参考Effective Java一书中所述.
//TODO 解释为什么
//这个方法是给subList用的
    protected void removeRange(int fromIndex, int toIndex) &#123;
        // Android-changed: Throw an IOOBE if toIndex < fromIndex as documented.
        // All the other cases (negative indices, or indices greater than the size
        // will be thrown by System#arrayCopy.
        if (toIndex < fromIndex) &#123;
            throw new IndexOutOfBoundsException("toIndex < fromIndex");
        &#125;

        modCount++;
        int numMoved = size - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) &#123;
            elementData[i] = null;
        &#125;
        size = newSize;
    &#125;


//移除所有C集合中包括的对象
    public boolean removeAll(Collection<?> c) &#123;
      //检查非空
        Objects.requireNonNull(c);
      //
        return batchRemove(c, false);
    &#125;

//这个方法设计的是在太妙了
        private boolean batchRemove(Collection<?> c, boolean complement) &#123;
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try &#123;
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                  //在这里实际上用了个双指针, 将后面的元素移动到被删除的元素上, 这样做的目的是一边删除(占位置)一边移动元素, 效率更高
                    elementData[w++] = elementData[r];
        &#125; finally &#123;
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
          //这里可能是为了做一些防御
            if (r != size) &#123;
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            &#125;
          
            if (w != size) &#123;
                // clear to let GC do its work
              //将w后续的元素释放
                for (int i = w; i < size; i++)
                    elementData[i] = null;
              //修改操作数
                modCount += size - w;
              //
                size = w;
                modified = true;
            &#125;
        &#125;
        return modified;
    &#125;

//将不属于C中的元素移除.
    public boolean retainAll(Collection<?> c) &#123;
        Objects.requireNonNull(c);
      //参考上述的描述, 这里complement = true, 刚好和removeAll相反.
      //这个方法设计的非常巧妙
        return batchRemove(c, true);
    &#125;
//这个没啥说的 非常简单,直接数组赋值就行了,注意不要越界的检查.
        public E set(int index, E element) &#123;
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

        E oldValue = (E) elementData[index];
        elementData[index] = element;
        return oldValue;
    &#125;

SubList以及迭代器

迭代器

先看几个方法

    /**
     * Returns an iterator over the elements in this list in proper sequence.
     *
     * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     *
     * @return an iterator over the elements in this list in proper sequence
     */
    public Iterator<E> iterator() &#123;
      //返回了Itr实例, 看ArrayList怎么实现的
        return new Itr();
    &#125;

 /**
     * An optimized version of AbstractList.Itr
     这里说的是一个优化过的AbstractList.Itr
     */
    private class Itr implements Iterator<E> &#123;
        // Android-changed: Add "limit" field to detect end of iteration.
        // The "limit" of this iterator. This is the size of the list at the time the
        // iterator was created. Adding & removing elements will invalidate the iteration
        // anyway (and cause next() to throw) so saving this value will guarantee that the
        // value of hasNext() remains stable and won't flap between true and false when elements
        // are added and removed from the list.
        protected int limit = ArrayList.this.size; // 迭代器的边界

        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount; //

        public boolean hasNext() &#123;
            return cursor < limit;
        &#125;

        @SuppressWarnings("unchecked")
        public E next() &#123;
            if (modCount != expectedModCount) //如果修改和期望不符, 则抛出多线程修改异常.
                throw new ConcurrentModificationException();
            int i = cursor;
            if (i >= limit) //边界检查
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1; //使用cursor增加1
            return (E) elementData[lastRet = i];
        &#125;

        public void remove() &#123;
            if (lastRet < 0)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();

            try &#123;
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
                limit--;
            &#125; catch (IndexOutOfBoundsException ex) &#123;
                throw new ConcurrentModificationException();
            &#125;
        &#125;

        @Override
        @SuppressWarnings("unchecked") //foreach的实现
        public void forEachRemaining(Consumer<? super E> consumer) &#123;
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) &#123;
                return;
            &#125;
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) &#123;
                throw new ConcurrentModificationException();
            &#125;
            while (i != size && modCount == expectedModCount) &#123;
                consumer.accept((E) elementData[i++]);
            &#125;
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;

            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        &#125;
    &#125;


   /**
     * An optimized version of AbstractList.ListItr
          优化过的迭代器, 能够前后移动,是一个双向的迭代器,并且支持增删改查.
     */
    private class ListItr extends Itr implements ListIterator<E> &#123;
        ListItr(int index) &#123;
            super();
            cursor = index;
        &#125;

        public boolean hasPrevious() &#123;
            return cursor != 0;
        &#125;

        public int nextIndex() &#123;
            return cursor;
        &#125;

        public int previousIndex() &#123;
            return cursor - 1;
        &#125;

        @SuppressWarnings("unchecked")
        public E previous() &#123;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            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];
        &#125;

        public void set(E e) &#123;
            if (lastRet < 0)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();

            try &#123;
                ArrayList.this.set(lastRet, e);
            &#125; catch (IndexOutOfBoundsException ex) &#123;
                throw new ConcurrentModificationException();
            &#125;
        &#125;

        public void add(E e) &#123;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();

            try &#123;
                int i = cursor;
                ArrayList.this.add(i, e);
                cursor = i + 1;
                lastRet = -1;
                expectedModCount = modCount;
                limit++;
            &#125; catch (IndexOutOfBoundsException ex) &#123;
                throw new ConcurrentModificationException();
            &#125;
        &#125;
    &#125;
ConcurrentModificationException

在使用迭代器的时候, 经常会遇见一个问题, 困扰大家很久.

举个栗子, 我明明没有在多个线程中修改List 为什么还会出现这个问题呢?

答案是看源码, 最好写一个demo主动报错debug就知道了

fun main() &#123;
    val mList = ArrayList<Int>(10)
    (1..10).forEach &#123; i ->
        mList.add(i) 
    &#125;
  //modCount = 10 对list做了10次add操作
    val itr = mList.iterator()
  // modCount = expectedModCount = 10
  

    while (itr.hasNext()) &#123;
      
      
      /**
              public E next() &#123;
            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];
        &#125;
                //这里会检查modeCount != expectedModCount
                final void checkForComodification() &#123;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        &#125;
      */
        val value = itr.next() //   
        if (value == 5)
            mList.remove(value) //此时modeCount = 11
    &#125;
&#125;
//或者使用foreach也可以, foreach的底层实现就是iterator

以上的代码就会报错.

分析原因可以参考注释.

主要原因就是在修改ArrayList的时候, 直接使用了ArrayList#remove这种操作, 使得modCountexpectedModCount不再相等, 解决方法就是如果使用迭代器遍历List, 那么在需要修改arrayList的时候, 也使用迭代器, 保证上述两个值始终相等.如下:

fun main() &#123;
    val mList = ArrayList<Int>(10)
    (1..10).forEach &#123; i ->
        mList.add(i)
    &#125;
    val itr = mList.iterator()

    while (itr.hasNext()) &#123;
        val value = itr.next()
        if (value == 5)
            itr.remove()
    &#125;
    print(mList)
&#125;
SubList

子串就代表的是ArrayList的子List, 上代码.

    private class SubList extends AbstractList<E> implements RandomAccess &#123;
        private final AbstractList<E> parent; //父List
        private final int parentOffset;  // 相对父List的偏移
        private final int offset; //偏移
        int size; // 大小

        SubList(AbstractList<E> parent,
                int offset, int fromIndex, int toIndex) &#123;
            this.parent = parent;
            this.parentOffset = fromIndex;
            this.offset = offset + fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = ArrayList.this.modCount;
        &#125;
                //同ArrayList, 修改的是父List
        public E set(int index, E e) &#123;
            rangeCheck(index);
            checkForComodification();
            E oldValue = ArrayList.this.elementData(offset + index);
            ArrayList.this.elementData[offset + index] = e;
            return oldValue;
        &#125;
                //同上
        public E get(int index) &#123;
            rangeCheck(index);
            checkForComodification();
            return ArrayList.this.elementData(offset + index);
        &#125;
                
        public int size() &#123;
            checkForComodification();
            return this.size;
        &#125;

        public void add(int index, E e) &#123;
            rangeCheckForAdd(index);
            checkForComodification();
            parent.add(parentOffset + index, e);
            this.modCount = parent.modCount;
            this.size++;
        &#125;

        public E remove(int index) &#123;
            rangeCheck(index);
            checkForComodification();
            E result = parent.remove(parentOffset + index);
            this.modCount = parent.modCount;
            this.size--;
            return result;
        &#125;

        protected void removeRange(int fromIndex, int toIndex) &#123;
            checkForComodification();
            parent.removeRange(parentOffset + fromIndex,
                               parentOffset + toIndex);
            this.modCount = parent.modCount;
            this.size -= toIndex - fromIndex;
        &#125;

        public boolean addAll(Collection<? extends E> c) &#123;
            return addAll(this.size, c);
        &#125;

        public boolean addAll(int index, Collection<? extends E> c) &#123;
            rangeCheckForAdd(index);
            int cSize = c.size();
            if (cSize==0)
                return false;

            checkForComodification();
            parent.addAll(parentOffset + index, c);
            this.modCount = parent.modCount;
            this.size += cSize;
            return true;
        &#125;

        public Iterator<E> iterator() &#123;
            return listIterator();
        &#125;

        public ListIterator<E> listIterator(final int index) &#123;
            checkForComodification();
            rangeCheckForAdd(index);
            final int offset = this.offset;

            return new ListIterator<E>() &#123;
                int cursor = index;
                int lastRet = -1;
                int expectedModCount = ArrayList.this.modCount;

                public boolean hasNext() &#123;
                    return cursor != SubList.this.size;
                &#125;

                @SuppressWarnings("unchecked")
                public E next() &#123;
                    checkForComodification();
                    int i = cursor;
                    if (i >= SubList.this.size)
                        throw new NoSuchElementException();
                    Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length)
                        throw new ConcurrentModificationException();
                    cursor = i + 1;
                    return (E) elementData[offset + (lastRet = i)];
                &#125;

                public boolean hasPrevious() &#123;
                    return cursor != 0;
                &#125;

                @SuppressWarnings("unchecked")
                public E previous() &#123;
                    checkForComodification();
                    int i = cursor - 1;
                    if (i < 0)
                        throw new NoSuchElementException();
                    Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length)
                        throw new ConcurrentModificationException();
                    cursor = i;
                    return (E) elementData[offset + (lastRet = i)];
                &#125;

                @SuppressWarnings("unchecked")
                public void forEachRemaining(Consumer<? super E> consumer) &#123;
                    Objects.requireNonNull(consumer);
                    final int size = SubList.this.size;
                    int i = cursor;
                    if (i >= size) &#123;
                        return;
                    &#125;
                    final Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length) &#123;
                        throw new ConcurrentModificationException();
                    &#125;
                    while (i != size && modCount == expectedModCount) &#123;
                        consumer.accept((E) elementData[offset + (i++)]);
                    &#125;
                    // update once at end of iteration to reduce heap write traffic
                    lastRet = cursor = i;
                    checkForComodification();
                &#125;

                public int nextIndex() &#123;
                    return cursor;
                &#125;

                public int previousIndex() &#123;
                    return cursor - 1;
                &#125;

                public void remove() &#123;
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

                    try &#123;
                        SubList.this.remove(lastRet);
                        cursor = lastRet;
                        lastRet = -1;
                        expectedModCount = ArrayList.this.modCount;
                    &#125; catch (IndexOutOfBoundsException ex) &#123;
                        throw new ConcurrentModificationException();
                    &#125;
                &#125;

                public void set(E e) &#123;
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

                    try &#123;
                        ArrayList.this.set(offset + lastRet, e);
                    &#125; catch (IndexOutOfBoundsException ex) &#123;
                        throw new ConcurrentModificationException();
                    &#125;
                &#125;

                public void add(E e) &#123;
                    checkForComodification();

                    try &#123;
                        int i = cursor;
                        SubList.this.add(i, e);
                        cursor = i + 1;
                        lastRet = -1;
                        expectedModCount = ArrayList.this.modCount;
                    &#125; catch (IndexOutOfBoundsException ex) &#123;
                        throw new ConcurrentModificationException();
                    &#125;
                &#125;

                final void checkForComodification() &#123;
                    if (expectedModCount != ArrayList.this.modCount)
                        throw new ConcurrentModificationException();
                &#125;
            &#125;;
        &#125;

        public List<E> subList(int fromIndex, int toIndex) &#123;
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, offset, fromIndex, toIndex);
        &#125;

        private void rangeCheck(int index) &#123;
            if (index < 0 || index >= this.size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        &#125;

        private void rangeCheckForAdd(int index) &#123;
            if (index < 0 || index > this.size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        &#125;

        private String outOfBoundsMsg(int index) &#123;
            return "Index: "+index+", Size: "+this.size;
        &#125;

        private void checkForComodification() &#123;
            if (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
        &#125;

        public Spliterator<E> spliterator() &#123;
            checkForComodification();
            return new ArrayListSpliterator<E>(ArrayList.this, offset,
                                               offset + this.size, this.modCount);
        &#125;
    &#125;

LinkedList

链表 ,使用引用(指针)将各个节点串联起来的一种数据结构, 在内存中的存储地址是非连续的.

先看一下LinkedList实现了哪些接口.

public interface Queue<E> extends Collection<E> &#123;
  boolean add(E e);
  boolean offer(E e);
  E remove();
  E poll(); //retrieves and remove the head of this queue
  E element();// retrieves the head but not remove, throw exception if queue is empty
  E peek();// retrieves the head but not remove. not throw exception.
&#125;

public interface Deque<E> extends Queue<E> &#123;
  //,,,,
&#125;
public interface List<E> extends Collection<E> &#123;
  
&#125;
public abstract class AbstractSequentialList<E> extends AbstractList<E> &#123;
&#125;

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable&#123;
    
    &#125;

节点

    private static class Node<E> &#123;
        E item; //存储的元素
        Node<E> next; //前向
        Node<E> prev; //后向

        Node(Node<E> prev, E element, Node<E> next) &#123;
            this.item = element;
            this.next = next;
            this.prev = prev;
        &#125;
    &#125;

成员变量

 transient int size = 0; //size 在序列化时不进行序列化
    /**
     * Pointer to first node.
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
  transient Node<E> first; //第一个节点
    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
  transient Node<E> last; //最后一个节点.

构造函数

    /**
     * Constructs an empty list.
     */
    public LinkedList() &#123;
    &#125;

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param  c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public LinkedList(Collection<? extends E> c) &#123;
        this();
        addAll(c);
    &#125;

方法分析

增删改查

    /**
     * Links e as first element.
     */
    private void linkFirst(E e) &#123;
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    &#125;
// 将指定的元素插入到list的开头.  
      public void addFirst(E e) &#123;
        linkFirst(e);
    &#125;
    /**
     * Links e as last element.
     */
    void linkLast(E e) &#123;
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    &#125;
    /**
     * Appends the specified element to the end of this list.
     *
     * <p>This method is equivalent to &#123;@link #add&#125;.
     *
     * @param e the element to add
     */
    public void addLast(E e) &#123;
        linkLast(e);
    &#125;
    /**
     * Appends the specified element to the end of this list.
     *
     * <p>This method is equivalent to &#123;@link #addLast&#125;.
     *
     * @param e element to be appended to this list
     * @return &#123;@code true&#125; (as specified by &#123;@link Collection#add&#125;)
     */
    public boolean add(E e) &#123;
        linkLast(e);
        return true;
    &#125;
public boolean addAll(Collection<? extends E> c) &#123;
   return addAll(size, c);
&#125;



public boolean addAll(int index, Collection<? extends E> c) &#123;
              //位置检查
        checkPositionIndex(index);
                    //将C转换为array
        Object[] a = c.toArray();
              //a的长度
        int numNew = a.length;
        if (numNew == 0)
            return false;
                //两个node
        Node<E> pred, succ;
        //如果刚好是到尾部, 将pred指向last
        if (index == size) &#123;
            succ = null;
            pred = last;
        &#125; else &#123;
        //否则在指定的index处插入.
            succ = node(index);
            pred = succ.prev;
        &#125;
        //将元素逐个插入到list中
        for (Object o : a) &#123;
            @SuppressWarnings("unchecked") E e = (E) o;
            Node<E> newNode = new Node<>(pred, e, null);
            if (pred == null)
                first = newNode;
            else
                pred.next = newNode;
            pred = newNode;
        &#125;
                //如果succ是null则, last=pred (last指向最后一个非空元素)
        if (succ == null) &#123;
            last = pred;
        &#125; else &#123;
          //如果succ不为空, 那么将pred和succ连接起来.
            pred.next = succ;
            succ.prev = pred;
        &#125;
                //size增加number
        size += numNew;
              //modCount自增.
        modCount++;
        return true;
    &#125;

        //位置检查.
    private void checkPositionIndex(int index) &#123;
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    &#125;
  /**
     * Tells if the argument is the index of a valid position for an
     * iterator or an add operation.
     */
    private boolean isPositionIndex(int index) &#123;
        return index >= 0 && index <= size;
    &#125;
删除
    //移除首个元素并返回
        public E removeFirst() &#123;
        final Node<E> f = first;
        if (f == null)
          //注意first == null会抛出异常
            throw new NoSuchElementException();
       //详细方法
        return unlinkFirst(f);
    &#125;


    /**
     * Unlinks non-null first node f.
     * 整个函数将移除头部, 并将头部指向头部的下一个元素.
     */
    private E unlinkFirst(Node<E> f) &#123;
        // assert f == first && f != null;
        final E element = f.item;
        final Node<E> next = f.next;
        f.item = null;
        f.next = null; // help GC
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    &#125;

    /**
     * Removes and returns the last element from this list.
     *
     * @return the last element from this list
     * @throws NoSuchElementException if this list is empty
     */
    //移除末尾元素
    public E removeLast() &#123;
        final Node<E> l = last;
        if (l == null)
            //注意last == null会抛出异常
            throw new NoSuchElementException();
        //详细方法
        return unlinkLast(l);
    &#125;

    /**
     * Unlinks non-null last node l.
     */
    private E unlinkLast(Node<E> l) &#123;
        // assert l == last && l != null;
        final E element = l.item;
        final Node<E> prev = l.prev;
        l.item = null;
        l.prev = null; // help GC
        last = prev;
        if (prev == null)
            first = null;
        else
            prev.next = null;
        size--;
        modCount++;
        return element;
    &#125;

/**
* 移除函数.
*/
        public boolean remove(Object o) &#123;
        if (o == null) &#123;
            for (Node<E> x = first; x != null; x = x.next) &#123;
                if (x.item == null) &#123;
                    unlink(x);
                    return true;
                &#125;
            &#125;
        &#125; else &#123;
            for (Node<E> x = first; x != null; x = x.next) &#123;
                if (o.equals(x.item)) &#123;
                    unlink(x);
                    return true;
                &#125;
            &#125;
        &#125;
        return false;
    &#125;

    /**
     * Unlinks non-null node x.
     */
            E unlink(Node<E> x) &#123;
        // assert x != null;
        final E element = x.item; //当前
        final Node<E> next = x.next; // 前向节点
        final Node<E> prev = x.prev; // 后向节点

        if (prev == null) &#123;  //边界
            first = next;
        &#125; else &#123;
            prev.next = next;
            x.prev = null;
        &#125;

        if (next == null) &#123;  //边界
            last = prev;
        &#125; else &#123;
            next.prev = prev;
            x.next = null;
        &#125;

        x.item = null; // 释放元素
        size--;  // size自减
        modCount++; //修改计数自增
        return element;
    &#125;

    public E remove(int index) &#123;
        checkElementIndex(index); //检查index是否在边界之内, 否则抛出数组越界异常.
        return unlink(node(index));
    &#125;
WechatIMG23

改就一个接口, 直接将制定的index上的元素置为指定的元素

    /**
     * Replaces the element at the specified position in this list with the
     * specified element.
     *
     * @param index index of the element to replace
     * @param element element to be stored at the specified position
     * @return the element previously at the specified position
     * @throws IndexOutOfBoundsException &#123;@inheritDoc&#125;
     */
    public E set(int index, E element) &#123;
        checkElementIndex(index);
        Node<E> x = node(index);
        E oldVal = x.item;
        x.item = element;
        return oldVal;
    &#125;
    /**
     * Returns the element at the specified position in this list.
     *
     * @param index index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException &#123;@inheritDoc&#125;
     */
    public E get(int index) &#123;
        checkElementIndex(index);
        return node(index).item;
    &#125;
//注意这里返回是非空的
    /**
     * Returns the (non-null) Node at the specified element index.
     */
    Node<E> node(int index) &#123;
        // assert isElementIndex(index);

        if (index < (size >> 1)) &#123;
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        &#125; else &#123;
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        &#125;
    &#125;

    /**
     * Returns &#123;@code true&#125; if this list contains the specified element.
     * More formally, returns &#123;@code true&#125; if and only if this list contains
     * at least one element &#123;@code e&#125; such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     *
     * @param o element whose presence in this list is to be tested
     * @return &#123;@code true&#125; if this list contains the specified element
     */
    public boolean contains(Object o) &#123;
        return indexOf(o) != -1;
    &#125;
//索引指定对象o
    public int indexOf(Object o) &#123;
        int index = 0;
      //如果o是空的, 找到第一个null元素
        if (o == null) &#123;
            for (Node<E> x = first; x != null; x = x.next) &#123;
                if (x.item == null)
                    return index;
                index++;
            &#125;
          //否则找到和o相等的元素,并返回index.
        &#125; else &#123;
            for (Node<E> x = first; x != null; x = x.next) &#123;
                if (o.equals(x.item))
                    return index;
                index++;
            &#125;
        &#125;
        return -1;
    &#125;
一些其他特殊操作

peek 返回链表头但不删除

poll 返回链表且删除元素

offer 将指定元素添加到链表末尾

每个方法都有xxFirst xxLast

此外, 还有类似栈的操作

push添加到表头(入栈)

pop 将表头元素移除(出栈)

Comments

⬆︎TOP