ArrayList源码(3)

来源:互联网 发布:3dmax软件打不开 编辑:程序博客网 时间:2024/06/05 05:53

前两篇写了add和remove相关的源码,现在剩下的是零散的一些和Itr、SubList、ListItr几个相关的代码,这些应用次数也多但是其中相似的代码较多。
先说零散的几个:
trimToSize()是减少存储使用的字符序列 ,如果缓冲区大于必要保持其当前的字符序列,那么它可能会调整大小,以成为更加节省空间.

public void trimToSize() {    modCount++;    int oldCapacity = elementData.length;    if (size < oldCapacity) {        elementData = Arrays.copyOf(elementData, size);    }}

之后contains()方法和indexOf()、lastIndexOf()相关:

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;}public int lastIndexOf(Object o) {    if (o == null) {        for (int i = size-1; i >= 0; i--)            if (elementData[i]==null)                return i;    } else {        for (int i = size-1; i >= 0; i--)            if (o.equals(elementData[i]))                return i;    }    return -1;}

从源码中看出contains()方法是使用indexOf来进行判断是否存在,indexOf()方法是从数组头部开发对比是否有相同的,lastIndexOf()方法是从尾部开发进行对比。

public Object clone() {    try {        @SuppressWarnings("unchecked")            ArrayList<E> v = (ArrayList<E>) super.clone();        v.elementData = Arrays.copyOf(elementData, size);        v.modCount = 0;        return v;    } catch (CloneNotSupportedException e) {        // this shouldn't happen, since we are Cloneable        throw new InternalError();    }}

clone()克隆数组,《Effective Java》的第11条中说“谨慎地覆盖clone”里面讲了很多clone的东西和注意事项,大家可以去看一眼。
我看别的博主写的:如何巧妙的使用ArrayList的Clone方法

private void writeObject(java.io.ObjectOutputStream s)    throws java.io.IOException{    // Write out element count, and any hidden stuff    int expectedModCount = modCount;    s.defaultWriteObject();    // Write out array length    s.writeInt(elementData.length);    // Write out all elements in the proper order.    for (int i=0; i<size; i++)        s.writeObject(elementData[i]);    if (modCount != expectedModCount) {        throw new ConcurrentModificationException();    }}private void readObject(java.io.ObjectInputStream s)    throws java.io.IOException, ClassNotFoundException {    // Read in size, and any hidden stuff    s.defaultReadObject();    // Read in array length and allocate array    int arrayLength = s.readInt();    Object[] a = elementData = new Object[arrayLength];    // Read in all elements in the proper order.    for (int i=0; i<size; i++)        a[i] = s.readObject();}

ArrayList上重写writeObject和readObject,当其序列化的时候将会映射调用该方法。之后如果有机会学习ObjectOutputStream的源码是再仔细研究里面的具体方法使用。

零散的几个我们看了,现在我们接着看关于ArrayList的Iterator相关的源码:

public ListIterator<E> listIterator(int index) {    if (index < 0 || index > size)        throw new IndexOutOfBoundsException("Index: "+index);    return new ListItr(index);}public ListIterator<E> listIterator() {    return new ListItr(0);}public Iterator<E> iterator() {    return new Itr();}

这是其相关的三个创建方法,其中iterator()直接创建Itr类,另外两个是创建ListItr类,这两个类是ArrayList的两个内部类其定义名为:

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;    .....}private class ListItr extends Itr implements ListIterator<E> {    ListItr(int index) {        super();        cursor = index;    }       .....}

他们的关系是有关联的,在源码中Itr类内部的方法只有四个而且都相关:

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

因为我看这些方法都简单明了,其中注意一下在remove()方法中的expectedModCount = modCount;在这里又进行了一次赋值,是因为在remove移除的时候modCount的数值发生了改变所以要重新进行复制,因为在checkForComodification()方法中如果检测到他们两个值不相同时,这个检查是可以避免一些可能引起跌代错误的add()或remove()等危险操作。在AbstractList中,使用了一个简单的机制来规避这些风险。 这就是modCount和expectedModCount的作用所在。
在ListItr类中,其中的方法都有类似当进行改动ArrayList的时候回调用ArrayList.this.*的方法进行改变。

在subList()方法中产生了一个SubList类该类为ArrayList的内部类,其内方法和ArrayList的各种方法都是大同小异的,相当于将ArrayList的个别数据复制到一个新的List里面进行操作,而其内的方法就是这种操作的内容,但是当修改了该List的内容或者添加了其原来的ArrayList的内容是跟随着改变的,其主要形成的方法:

public List<E> subList(int fromIndex, int toIndex) {    subListRangeCheck(fromIndex, toIndex, size);    return new SubList(this, 0, fromIndex, toIndex);}static void subListRangeCheck(int fromIndex, int toIndex, int size) {    if (fromIndex < 0)        throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);    if (toIndex > size)        throw new IndexOutOfBoundsException("toIndex = " + toIndex);    if (fromIndex > toIndex)        throw new IllegalArgumentException("fromIndex(" + fromIndex +                                           ") > toIndex(" + toIndex + ")");}
public void add(int index, E e) {    rangeCheckForAdd(index);    checkForComodification();    parent.add(parentOffset + index, e);    this.modCount = parent.modCount;    this.size++;}

从该方法中就能看出形成新的SubList还是从原有的ArrayList上进行改变的。

原创粉丝点击