java核心之集合框架——ArrayList源码分析

——每天的寥寥几笔,坚持下去,将会是一份沉甸甸的积累。


了解了上一篇java核心之集合框架——HashMap源码分析的源码分析过程,再来看ArrayList那就是小菜一碟了。

1.内部数据结构:Object[]数组

2.一般的增删add,remove函数,就是对数组进行操作,比较简单,这里略过。

3.几个需要注意和比较不好理解的函数

首先是toArray函数

ArrayList类下面:
public Object[] toArray() {
    return Arrays.copyOf(elementData, size);//返回一个大小为size,内容和elementData数组一样的数组
}
public <T> T[] toArray(T[] a) {
	//必须通过下面基于反射机制写的函数,不能new Object[]b; b=a;然后return T[]b;强转失败,回报运行时异常
    if (a.length < size)
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

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

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    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;
}

System类下面:
public static native void arraycopy(Object src,int srcPos,Object dest,int destPos,int length);
//原数组。原数组开始的位置,要复制到的目标数组,目标数组的开始位置,要复制的长度
//该方法是用了native关键字,调用的为C++编写的底层函数,可见其为JDK中的底层函数。 

其次是r
etainAll(Collection<?> c)和removeAll(Collection<?> c)

public boolean removeAll(Collection<?> c) {//保留两个集合的非公共部分
    return batchRemove(c, false);
}
public boolean retainAll(Collection<?> 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 {
        for (; r < size; r++)
            if (c.contains(elementData[r]) == complement)//complement=true,则将找到的相同元素从头开始覆盖elementData数组本身
                elementData[w++] = elementData[r];
    } finally {
        if (r != size) {//正常情况下,for循环结束,r=size,不能于则说明有异常抛出
            System.arraycopy(elementData, r,elementData, w,size - r);将r后面的数组内容复制到w后面
            w += size - r;//
        }
        if (w != size) {//将w后面无用的赋值为null
            for (int i = w; i < size; i++)
                elementData[i] = null;
            modCount += size - w;
            size = w;
            modified = true;//w != size ,表明有改动,modified被置为true
        }
    }
    return modified;
}

4.视图类相关:迭代器和SubList

—-迭代器—-

  两个方法返回两个Iterator对象,前者支持双向遍历,后者只支持往后遍历
    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }
    public Iterator<E> iterator() {
        return new Itr();
    }
  具体实现类:
private class Itr implements Iterator<E> {//只支持单向的next往后遍历
        int cursor;
        //cursor:返回下一个元素(Next操作)的索引,最大=size()-1
        //“越过”哪个元素,就返回该元素下一个元素(指Next)的index

        int lastRet = -1;
        //lastRet:返回最近一个调用Next或者previous操作“越过”哪个元素,就返回该元素的index
        //remove过后,有被置为-1

        int expectedModCount = modCount;//修改次数

        public boolean hasNext() {
            return cursor != size;
        }

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

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

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

    private class ListItr extends Itr implements ListIterator<E> {//支持双向遍历,next or previous
        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();
            }
        }
    }


SubList—-

class SubList<E> extends AbstractList<E> {
//继承AbstractList,几乎把所有方法覆写了,使得subList对象拥有和arrayList对象一样的各种功能。
//代码很简单,就是重写的时候用新的索引。
 private final AbstractList<E> l;
    private final int offset;
    private int size;

    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > list.size())
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
        l = list;
        offset = fromIndex;
        size = toIndex - fromIndex;
        this.modCount = l.modCount;
    }

    public E set(int index, E element) {
        rangeCheck(index);
        checkForComodification();
        return l.set(index+offset, element);
    }

    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        return l.get(index+offset);
    }

    public int size() {
        checkForComodification();
        return size;
    }

    public void add(int index, E element) {
        rangeCheckForAdd(index);
        checkForComodification();
        l.add(index+offset, element);
        this.modCount = l.modCount;
        size++;
    }

    public E remove(int index) {
        rangeCheck(index);
        checkForComodification();
        E result = l.remove(index+offset);
        this.modCount = l.modCount;
        size--;
        return result;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        l.removeRange(fromIndex+offset, toIndex+offset);
        this.modCount = l.modCount;
        size -= (toIndex-fromIndex);
    }

    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }

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

        checkForComodification();
        l.addAll(offset+index, c);
        this.modCount = l.modCount;
        size += cSize;
        return true;
    }

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

    public ListIterator<E> listIterator(final int index) {
        checkForComodification();
        rangeCheckForAdd(index);

        return new ListIterator<E>() {
            private final ListIterator<E> i = l.listIterator(index+offset);

            public boolean hasNext() {
                return nextIndex() < size;
            }

            public E next() {
                if (hasNext())
                    return i.next();
                else
                    throw new NoSuchElementException();
            }

            public boolean hasPrevious() {
                return previousIndex() >= 0;
            }

            public E previous() {
                if (hasPrevious())
                    return i.previous();
                else
                    throw new NoSuchElementException();
            }

            public int nextIndex() {
                return i.nextIndex() - offset;
            }

            public int previousIndex() {
                return i.previousIndex() - offset;
            }

            public void remove() {
                i.remove();
                SubList.this.modCount = l.modCount;
                size--;
            }

            public void set(E e) {
                i.set(e);
            }

            public void add(E e) {
                i.add(e);
                SubList.this.modCount = l.modCount;
                size++;
            }
        };
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new SubList<>(this, fromIndex, toIndex);
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

    private void checkForComodification() {
        if (this.modCount != l.modCount)
            throw new ConcurrentModificationException();
    }
}


5.最后知道Arraylist实现了标记接口RandomAccess接口,该接口会告知虚拟机对该数据类型进行随机访问查找,看看查找效率是否高效,不高效会报错。

    原文作者:java集合源码分析
    原文地址: https://blog.csdn.net/sum_rain/article/details/40059363
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞