jdk8源码2---集合1---ArrayList

一、 签名

 

public class ArrayList<E> extends AbstractList<E>

 

        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

 

可序列化,可以支持快速的随机访问,可以被克隆。

 

二、成员变量

 

private static final int DEFAULT_CAPACITY = 10; // 默认大小为10

 

private static final Object[] EMPTY_ELEMENTDATA = {};

 

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

 

transient Object[] elementData;  // arrayList中的数据

 

private int size;  // 当前状态下的arraylist中的数据量。

 

Protect transient int modCount = 0; // 记录被修改的次数。

 

 

 

三、构造方法

 

public ArrayList(int initialCapacity) {  // 可以指定容量的大小。

 

        if (initialCapacity > 0) {  //如果指定了容量大小,那么就会创建指定容量的list

 

            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; //使用默认的数据大小

 

}//但是,DEFAULTCAPACITY_EMPTY_ELEMENTDATA的大小也是0,为什么呢?是在第一次调用add的时候将其初始化的。见add方法。

 

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;

 

        }

 

    }

 

 

 

四、成员方法

 

1.1     add

 

public boolean add(E e) {

 

    ensureCapacityInternal(size + 1);  // Increments modCount!!

 

    elementData[size++] = e;

 

    return true;

 

}

 

private void ensureCapacityInternal(int minCapacity) { //minCapacity当前的容量

 

       if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//此时即第一次add

 

       minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//设置容量为10

 

    }

 

ensureExplicitCapacity(minCapacity); // 需要的最小容量。

 

}

 

private void ensureExplicitCapacity(int minCapacity) {

 

        modCount++;

 

        // overflow-conscious code

 

        if (minCapacity - elementData.length > 0) //需要扩容了。

 

            grow(minCapacity); //扩容的大小为目前的size+1

 

    }

 

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);

 

    }

 

private static int hugeCapacity(int minCapacity) {

 

        if (minCapacity < 0) // overflow

 

            throw new OutOfMemoryError();

 

        return (minCapacity > MAX_ARRAY_SIZE) ?

 

            Integer.MAX_VALUE :

 

            MAX_ARRAY_SIZE;// Integer.MAX_VALUE-8

 

    }

 

扩容的算法是:

 

1.  指定下次预期扩容的为当前容量的二分之三倍,称之为新容量(newCapacity),如果需要的最小容量(minCapacity)大于新容量(newCapacity),那么就以需要的最小容量(minCapacity)扩容。如果新容量(newCapacity)大于了规定的最大数组大小(Integr.MAX_VALUE-8),那么就将需要的最小容量(minCapacity)和最大数组大小(Integr.MAX_VALUE-8)比较,取大。如果最小容量(minCapacity)大于规定的最大数组大小(Integr.MAX_VALUE-8),扩容后的数组大小为Integr.MAX_VALUE

 

1.2 public void add(int index,E element)

 

    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 static native void arraycopy(Object src,  int  srcPos,

 

               Object dest, int destPos, int length);

 

 

 

添加一个集合中的所有元素的时候,调用的是System.arraycopy方法。注意,调用的这个方法是一个本地方法。

 

1.3 public boolean addAll(Collection<?extends E> c)

 

public boolean addAll(Collection<? extends E> c) {

 

        Object[] a = c.toArray();

 

        int numNew = a.length;

 

        ensureCapacityInternal(size + numNew);  // Increments modCount

 

        System.arraycopy(a, 0, elementData, size, numNew);

 

        size += numNew;

 

        return numNew != 0;

 

    }

 

    *System.arraycopy

 

    像其他的和添加相关的方法都是差不多了。不一一列举。

 

2.1 public E remove(int index)

 

    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;

 

    }

 

    很简单,不多说。

 

2.2 public boolean remove(Object 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;

 

    }

 

private void fastRemove(int index) {

 

        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

 

    }

 

    同样的 内涵之处还是在System.arraycopy

 

2.3 public booleanremoveAll(Collection<?> c)

 

public boolean removeAll(Collection<?> c) {

 

        Objects.requireNonNull(c);

 

        return batchRemove(c, false);

 

    }

 

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];

 

        } finally {

 

            // 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;

 

    }

 

3.1 public E get(int index)

 

public E get(int index) {

 

    rangeCheck(index); 

 

return elementData(index);

 

}

 

E elementData(int index) {

 

        return (E) elementData[index];   // 毕竟是数组。

 

    }

 

 

 

4. public E set(int index, E element)

 

public E set(int index, E element) {

 

        rangeCheck(index);

 

        E oldValue = elementData(index);

 

        elementData[index] = element;   //数组的性质、

 

        return oldValue;

 

    }

 

 

 

5. public boolean contains(Object o)

 

public boolean contains(Object o) {

 

        return indexOf(o) >= 0;

 

    }

 

public int indexOf(Object o) {

 

        if (o == 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;

 

    }

 

 

 

 

 

五、遍历方式

 

1.  for循环。

 

2.  fori

 

3.  Iterator、ArrayList.iterator();

 

public Iterator<E> iterator() { return new Itr(); }

 

private class Itr implements Iterator<E> {

 

        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() {

 

            return cursor != size;

 

        }

 

        @SuppressWarnings("unchecked")

 

        public E next() {

 

            checkForComodification();

 

            int i = cursor;   // 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];

 

        }

 

 

 

        public void remove() {

 

            if (lastRet < 0)

 

                throw new IllegalStateException();

 

            checkForComodification();

 

            try {

 

                ArrayList.this.remove(lastRet);

 

                cursor = lastRet;

 

                lastRet = -1;

 

                expectedModCount = modCount;

 

            } catch (IndexOutOfBoundsException ex) {

 

                throw new ConcurrentModificationException();

 

            }

 

        }

 

 

 

        @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();

 

        }

 

 

 

        final void checkForComodification() {

 

            if (modCount != expectedModCount)

 

                throw new ConcurrentModificationException();

 

        }

 

    }

 

 

 

定义了一个内部类,实现了Iterator接口。实现其方法。

 

用一个变量来记录当前访问的元素的地址,这个变量必须是成员变量。

 

不定义内部类,直接用ArrayList实现Iterator接口,也是可以的。

 

 

 

 

 

总结:

 

    先说一些老生常谈的事情吧。

 

    1.ArrayList的实现原理是数组。

 

    2.容量不固定,最大值是Integer.MAX

 

    3.元素允许为null。

 

4.有序(重申:放入和取出是有序的)

 

    5.非线程安全。

 

       并发环境下,要么加锁,要么在初始化时使用Collection.synchronizeList(newArrayList());

 

6.遍历时的效率问题:

 

for循环要比迭代器快。原因是ArrayList继承了RandomAccess,支持快速的随机访问,而迭代器都是基于ArrayList方法和数组直接操作的。

 

 

 

7.add,remove值类型的数据时可能会涉及拆装箱操作。

 

 

 

补充一下:

 

    Fail-fast机制,也叫作快速失败机制,是java集合中的一种错误检测机制。

 

    ArrayList中,有个modCount的变量,每次进行add,set,remove等操作,都会执行modCount++.

 

在获取ArrayList迭代器时,会将ArrayList中的modCount保存在迭代中,每次执行add,set,remove等操作,都会执行一次检查,都会调用checkForComodification方法,对modCount进行比较,如果迭代器中的modCount和list中的modCount不同,就会抛出ConcurrentModificationException。

最后


如果你觉得写的还不错,就关注下公众号呗,关注后,有点小礼物回赠给你。
你可以获得5000+电子书,java,springCloud,adroid,python等各种视频教程,IT类经典书籍,各种软件的安装及破解教程。
希望一块学习,一块进步!

posted @ 2018-06-10 13:36  方家小白  阅读(14)  评论(0编辑  收藏  举报