ArrayList 1.8

1 篇文章 0 订阅
1 篇文章 0 订阅

ArrayList源码分析

ArrayList 是一个可动态扩展的数组,其底层实现是数组。

  1. 它是如何实现动态扩容的?
  2. 调用无参构造创建的ArrayList 对象,初始化的容量真的为10吗?
  3. elementData 被transient 修饰,那它是如何实现序列化与反序列化的?
  4. ArrayList 增删改查的方法时间复杂度又各是多少?
  5. ArrayList 的数组越界的定义规则是什么?
  6. ConcurrentModificationException 定义规则是什么?
  7. 为什么在ArrayList 遍历中对其进行增删,会抛出ConcurrentModificationException异常,用迭代器对ArrayList 进行遍历的时候,调用迭代器的增删方法对ArrayList 进行增删的时候为什么不会抛出ConcurrentModificationException 异常?
属性
public class ArrayList<E> extends AbstractList<E> implements List<E>, 
	RandomAccess, Cloneable, java.io.Serializable {
	...
    private static final long serialVersionUID = 8683452581122892189L;
    // 化默认初始容量
    private static final int DEFAULT_CAPACITY = 10;
    /**
	 * 指定该ArrayList容量为0时,返回该空数组。
	 */
    private static final Object[] EMPTY_ELEMENTDATA = {};
    /**
	 * 当调用无参构造方法,返回的是该数组。刚创建一个ArrayList 时,其内数据量为0。
	 * 它与EMPTY_ELEMENTDATA的区别就是:该数组是默认返回的,而后者是在用户指定容量为0时返回。
	 */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    /**
	 * 存储ArrayList元素的数组缓冲区,ArrayList的容量是这个数组缓冲区的长度。
	 * 任何使用elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA清空ArrayList将在添加第一个元素时扩展为DEFAULT_CAPACITY。
	 **/
 	transient Object[] elementData;
    // ArrayList的实际元素大小(数组中包含的元素个数)
    private int size;
    /**
    * 要分配的数组的最大大小。
    * 一些VM在数组中保留一些头信息。
    * 尝试分配更大的数组可能会导致OutOfMemoryError:请求的数组大小超过VM限制
    **/
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

	/**
     * 这个属性是在AbstractList 类中的,记录对List 被修改的次数,主要使用是在`Iterator`,
     * 是防止在迭代的过程中集合被修改。在ArrayList的所有涉及结构变化的方法中都增加
     * modCount的值,包括:add()、remove()、addAll()、removeRange()及
     * clear()方法。这些方法每调用一次,modCount的值就加1。
     * 注:add()及addAll()方法的modCount的值是在其中调用的ensureCapacity()方法中增加的。
     */
    protected transient int modCount = 0;
    ......
}
构造方法
    /**
     * Constructs an empty list with the specified initial capacity.
     * 构造具有指定初始容量的 List。
     * @param  initialCapacity  List 的初始化容量
     * @throws IllegalArgumentException 如果初始化容量为负数时,抛出该异常
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     * 构造一个长度为10 的List,此时并不会直接构建一个长度为10的List 对象
     * 调用该构造生成的List 对象是长度为0的:DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}
     * 当调用add(E e)、add(int index, E element)、addAll(Collection<? extends E> c)、addAll(int index, Collection<? extends E> c) 才会调用ensureCapacityInternal(int minCapacity) 创建一个长度为10的List 对象
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * 按照集合迭代器返回元素的顺序构造包含指定集合的元素的List对象。
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
    	// 将集合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;
        }
    }
方法
序号返回类型方法时间复杂度
1booleanadd(E e)
将指定的元素追加到此lis的末尾
2voidadd(int index, E element)
将指定元素插入到列表中的指定位置。
3booleanaddAll(Collection<? extends E> c)
将指定的元素追加到此lis的末尾
4booleanaddAll(int index, Collection<? extends E> c)
将指定的元素追加到此lis的指定索引处
5voidclear()
从列表中删除所有元素。
6Objectclone()
返回此ArrayList实例的浅克隆。
7booleancontains(Object o)
如果此List 包含指定的元素,则返回true。
8voidensureCapacity(int minCapacity)
增加arraylist实例的容量,以确保它至少可以容纳由minCapacity参数指定的元素数(如果需要的话)
9voidforEach(Consumer<? super E> action)
为可迭代的每个元素执行给定的操作,直到处理完所有元素或操作引发异常为止。
10Eget(int index)
返回列表中指定位置的元素。
11intindexOf(Object o)
返回此列表中指定元素的第一个出现项的索引,如果该列表不包含该元素,则返回-1
12booleanisEmpty()
如果此列表不包含任何元素,则返回true。
13Iteratoriterator()
按特有的顺序返回列表中元素的Iterator 对象。
14intlastIndexOf(Object o)
回此列表中指定元素的最后一次出现的索引,如果该列表不包含该元素,则返回-1。
15ListIteratorlistIterator()
返回列表中元素的ListIteratorr对象(按特有的顺序)。
16ListIteratorlistIterator(int index)
从列表中的指定位置开始,返回列表中元素的ListIterator对象(按特有的顺序),。
17Eremove(int index)
移除列表中指定位置的元素。
18booleanremove(Object o)
从列表中删除指定元素的第一个出现项(如果存在)。
19booleanremoveAll(Collection<?> c)
从该列表中删除指定集合中包含的所有元素。
20booleanremoveIf(Predicate<? super E> filter)
移除此集合中满足给定predicate的所有元素
21voidremoveRange(int fromIndex, int toIndex)
返回列表中指定位置的元素。
22voidreplaceAll(UnaryOperator operator)
Replaces each element of this list with the result of applying the operator to that element.
23booleanretainAll(Collection<?> c) 只保留此列表中包含在指定集合中的元素。
24Eset(int index, E element)
用指定的元素替换列表中指定位置的元素。
25intsize()
返回此列表中的元素数量。
26voidsort(Comparator<? super E> c)
根据指定c对该列表进行排序。
27Spliteratorspliterator()
在其中的元素上创建一个late-binding 和 fail-fast Spliterator
28ListsubList(int fromIndex, int toIndex)
返回列表中指定的fromIndex(包含)和toIndex(不包含)之间的部分。
29Object[]toArray()
返回一个数组,该数组按特有的顺序(从第一个元素到最后一个元素),包含列表中的所有元素。
30<T> T[]toArray(T[] a)
返回一个数组,该数组按特有的顺序(从第一个元素到最后一个元素),包含列表中的所有元素; 返回数组的运行时类型是指定数组的运行时类型。
31voidtrimToSize()
将ArrayList实例的容量调整为列表的当前大小。

java里的clone分为:

  1. 浅复制(浅克隆):浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
  2. 深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍。
1. 添加方法
	/**
     * 将指定元素添加到列表末尾
     * 
     * 平均时间复杂度为 O(1),最坏的时间复杂度O(n)
     * 
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    
	/**
     * 将指定元素插入其中的指定位置列表。
     * 将当前位于该位置(如果有)的元素移动,并将右边的元素顺序往后移动一位
     * 
     * 最好的时间复杂度为:O(1),最坏的时间复杂度为 O(n),平均时间复杂度为:O(n)
     * 
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    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++;
    }
    
    /**
     * 将指定的元素追加到此lis的尾部
     * 
     * 时间复杂度为O(n)
     * 
     * @param c collection containing elements to be added to this list
     * @return <tt>true</tt> if this list changed as a result of the call
     * @throws NullPointerException if the specified collection is null
     */
    public boolean addAll(Collection<? extends E> c) {
    	// 将要添加的集合转成数组
        Object[] a = c.toArray();
        // 获取数组的长度
        int numNew = a.length;
        // 重新确认ArrayList 的容量
        ensureCapacityInternal(size + numNew);  // Increments modCount
        // 将要添加数据按原顺序一次追加到elementData 的尾部
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    /**
     * 将指定的元素追加到此lis指定索引处,并将此list 原来指定索引及之后的所有元素
     * 依次后移一位
     * 
     *  时间复杂度为O(n)
     * 
     * @param index index at which to insert the first element from the
     *              specified collection
     * @param c collection containing elements to be added to this list
     * @return <tt>true</tt> if this list changed as a result of the call
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @throws NullPointerException if the specified collection is null
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        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;
    }    
    
	// -----------------------------------------------------------------------------
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    /**
     * 要分配的数组的最大大小。
     * Some VMs reserve some header words in an array.
     * 尝试分配更大的数组可能会导致 OutOfMemoryError: R请求的数组大小超过VM限制
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * 增加能力,以确保它至少可以持有由最小容量参数指定的元素数量。
     *
     * @param minCapacity 所需的最小容量
     */
    private void grow(int minCapacity) {
    
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        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;
    }

java.lang.System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length):

  1. src:原数组
  2. srcPos:原数组的开始位置
  3. dest:目标数组
  4. destPos:目标数组的开始位置
  5. length:要拷贝的元素个数
2. 删除方法
	/**
   	* 
   	* 从列表中删除指定索引处的元素,并返回被删除的元素,如果它存在的话。
   	*/
	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;
    }
   	/**
   	* 
   	* 从列表中删除指定元素的第一个出现项,如果它存在的话。
   	* 如果列表不包含该元素,则它包含不变。更正式地说,删除索引最小的元素
   	*/
    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
    }
    /**
   	* 从该列表中删除索引位于fromIndex 到toIndex 两者之间的所有元素
   	* 包含 fromIndex; 排除:toIndex。
   	*/
    protected void removeRange(int fromIndex, int toIndex) {
        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++) {
            elementData[i] = null;
        }
        size = newSize;
    }
    /**
	* 从该列表中删除指定集合中包含的所有元素。
	*/
	public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }
	/**
	* 只保留集合中包含的所有元素,集合以外的元素都删除。
	*/
	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 {
            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. removeIf 方法
	/**
	* 
	*/
	public boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        // 找出要删除的元素
        // any exception thrown from the filter predicate at this stage
        // will leave the collection unmodified
        int removeCount = 0;
        final BitSet removeSet = new BitSet(size);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            @SuppressWarnings("unchecked")
            final E element = (E) elementData[i];
            if (filter.test(element)) {
            	// 将符合条件的索引存到 BigSet 集合中
                removeSet.set(i);
                removeCount++;
            }
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }

        // 将剩余元素移动到已删除元素所留下的空间上
        final boolean anyToRemove = removeCount > 0;
        if (anyToRemove) {
            final int newSize = size - removeCount;
            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
                // 如果removeSet 中含有 i,获得是 i + 1;没有时获得是 i 本身
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            for (int k=newSize; k < size; k++) {
                elementData[k] = null;  // Let gc do its work
            }
            this.size = newSize;
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }

        return anyToRemove;
    }
3.1 removeIf 方法的使用
	public void removeIfDemo() {
		List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        list.add("6");
        list.add("7");
        list.add("8");
        list.add("9");
        list.add("10");
        System.out.println(list);
        list.removeIf(l -> {
        	// Predicate 匿名实现类,重写test 方法
            if (l.equals("1")) {
                return true;
            } else {
                return false;
            }
        });
        /**
        * list.removeIf(new Predicate<String>() {
        * 	@Override
        * 	public boolean test(String s) {
        * 		if (s.equals("1")) {
		*			return true;
        *		} else {
        *			return false;
      	*		}
        *   }
        * });
        */
        System.out.println(list);
	}
	// 运行结果
	[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
	[2, 3, 4, 5, 6, 7, 8, 9, 10]
4. 替换方法
	/**
	* 替换list 集合中的元素
	*/
    @Override
    @SuppressWarnings("unchecked")
    public void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            elementData[i] = operator.apply((E) elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
4.1 replaceAll 方法的使用
	public void replaceAllDemo() {
		List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        list.add("6");
        list.add("7");
        list.add("8");
        list.add("9");
        list.add("10");
        System.out.println(list);
		list.replaceAll(l -> {
            if (!l.equals("2")) {
                return "11";
            } else {
                return l;
            }
        });
        // list.replaceAll(new UnaryOperator<String>() {
        //     @Override
        //     public String apply(String s) {
        //         if (!s.equals("2")) {
        //             return "11";
        //         } else {
        //             return s;
        //         }
        //     }
        // });
        System.out.println(list);
        // 运行结果
		[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
		[11, 2, 11, 11, 11, 11, 11, 11, 11, 11]
	}
5. sort 方法
	@Override
    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
5.1 sort 方法的使用
    public void sortDemo {
        ArrayList<Demo> list = new ArrayList<>();
        Demo demo = new Demo();
        demo.setAge(10);
        demo.setName("三三");
        list.add(demo);
        demo = new Demo();
        demo.setAge(20);
        demo.setName("尔尔");
        list.add(demo);
        demo = new Demo();
        demo.setAge(50);
        demo.setName("五五");
        list.add(demo);
        demo = new Demo();
        demo.setAge(2);
        demo.setName("琪琪");
        list.add(demo);
        System.out.println(list);
        list.sort((demo1, demo2) -> {
            if (demo1 == null || demo2 == null) {
                return 0;
            }

            if (demo1.getAge() > demo2.getAge()) {
                return 1;
            } else if (demo1.getAge() == demo2.getAge()) {
                return 0;
            } else {
                return -1;
            }
        });
        // list.sort(new Comparator<Demo>() {
        //     @Override
        //     public int compare(Demo demo1, Demo demo2) {
        //         if (demo1 == null || demo2 == null) {
        //             return 0;
        //         }
        //         if (demo1.getAge() > demo2.getAge()) {
        //             return 1;
        //         } else if (demo1.getAge() == demo2.getAge()) {
        //             return 0;
        //         } else {
        //             return -1;
        //         }
        //     }
        // });
        System.out.println(list);
    }

    private static class Demo {
        private String name;
        private int age;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "Demo{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    // 测试结果
	[Demo{name='三三', age=10}, Demo{name='尔尔', age=20}, Demo{name='五五', age=50}, Demo{name='琪琪', age=2}]
	[Demo{name='琪琪', age=2}, Demo{name='三三', age=10}, Demo{name='尔尔', age=20}, Demo{name='五五', age=50}]
6. forEach 方法
	
    @Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[i]);
        }
        // 在使用forEach方法在进行元素的操作的时候,
        // 发现ArrayList的数据发生了动,就由forEach方法抛出异常
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }
7. ArrayList 迭代器
7. 1 ListIterator
	/**
     * 返回列表中元素的列表迭代器,从列表中的指定位置开始遍历
     * An initial call to {@link ListIterator#previous previous} would
     * return the element with the specified index minus one.
     *
     * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }
	/**
     * 按特有的顺序返回列表中元素的ListIterator。
     *
     * <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 ListIterator<E> listIterator() {
        return new ListItr(0);
    }


    /**
     * An optimized version of AbstractList.ListItr
     */
    private class ListItr extends Itr implements ListIterator<E> {
        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();
            }
        }
    }
7. 2 Iterator
    /**
     * 按特有的顺序返回列表中元素的迭代器。
     *
     * <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() {
        return new Itr();
    }
    /**
     * An optimized version of AbstractList.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;
            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();
        }
    }
7. 3 Spliterator
	/**
     * Creates a late-binding and fail-fast Spliterator over the elements in this list.
     * 在此列表中的元素上创建延迟绑定(late-binding)和快速失败(fail-fast)的 Spliterator。
     * 
     * @since 1.8
     */
    @Override
    public Spliterator<E> spliterator() {
        return new ArrayListSpliterator<>(this, 0, -1, 0);
    }

    /** 
    * 基于索引的二分法,延迟初始化的Spliterator
    * */
    static final class ArrayListSpliterator<E> implements Spliterator<E> {

        private final ArrayList<E> list;
        // 当前位置(包含),advance/split操作时会修改
        private int index; // current index, modified on advance/split
        // 结束位置(不包含),-1 表示到最后一个元素
        private int fence; 
        // 用于存放list的modCount,
        private int expectedModCount; // initialized when fence set

        /** Create new spliterator covering the given  range */
        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                             int expectedModCount) {
            this.list = list; // OK if null unless traversed
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }
        
 		//获取结束位置(存在意义:首次初始化石需对fence 和expectedModCount 进行赋值)
        private int getFence() { // initialize fence to size on first use
            int hi; // (a specialized variant appears in method forEach)
            ArrayList<E> lst;
            if ((hi = fence) < 0) {
                if ((lst = list) == null)
                	// list 为 null时,fence=0
                    hi = fence = 0;
                else {
                	// 初始化expectedModCount 和 fence
                    expectedModCount = lst.modCount;
                    hi = fence = lst.size;
                }
            }
            return hi;
        }
		
		// 分割list,返回一个新分割出的spliterator实例
        public ArrayListSpliterator<E> trySplit() {
	        //hi 为当前的结束位置 lo 为起始位置
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null : // divide range in half unless too small
                new ArrayListSpliterator<E>(list, lo, index = mid,
                                            expectedModCount);
        }
		
		/**
		* 
		* 返回true 时,只表示可能还有元素未处理;返回false 时,没有剩余元素处理了
		* 该方法只处理首个所有未处理元素
		*/
        public boolean tryAdvance(Consumer<? super E> action) {
            if (action == null)
                throw new NullPointerException();
            int hi = getFence(), i = index;
            if (i < hi) {
                index = i + 1;
                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
                // 可以在accept 方法中定义处理的逻辑
                action.accept(e);
                // 检查 accept 方法中是否修改了list 的结构
                if (list.modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                return true;
            }
            return false;
        }
        
		// 顺序遍历处理所有剩下的元素
        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) {
                if ((hi = fence) < 0) {
                    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(e);
                    }
                    // 遍历结束判断是否变更过list 的结构
                    if (lst.modCount == mc)
                        return;
                }
            }
            throw new ConcurrentModificationException();
        }
		// 估算还剩下多少个元素需要遍历
        public long estimateSize() {
            return (long) (getFence() - index);
        }

        public int characteristics() {
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
        }
    }
7. 3 spliterator 方法的使用
	public static void demo1() {
        ArrayList<String> list = new ArrayList<> ();
        list.add ("1");
        list.add ("2");
        list.add ("3");
        list.add ("4");
        list.add ("5");
        list.add ("6");
        list.add ("7");
        list.add ("8");
        // iterator 长度为8
        Spliterator<String> iterator = list.spliterator (); 
        // iterator 长度为4,spliterator 长度为4
        Spliterator<String> spliterator = iterator.trySplit ();  
        // iterator 长度为4,spliterator 长度为2,stringSpliterator 长度为2
        Spliterator<String> stringSpliterator = spliterator.trySplit ();  
        // 只处理首个所有未处理的元素
        iterator.tryAdvance (l -> {
            out.print (l + " "); // 5 
        });
        System.out.println ();
        // 顺序遍历处理所有剩下的元素
        iterator.forEachRemaining (l -> {
            out.print (l + " "); // 6 7 8 
        });
        System.out.println ();
        spliterator.forEachRemaining (l -> {
            out.print (l + " ");// 3 4
        });
        System.out.println ();
        stringSpliterator.forEachRemaining (l -> {
            out.print (l + " ");// 1 2
        });
        System.out.println ();
    }
8. ArrayList 的Stream
	public static void demo2() {
        List<Integer> numbers = new ArrayList<> (Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9));
        for (int i = 0; i < 10; i++) {
            numbers.add (i + 10);
        }
        // stream 为集合创建串行流
        numbers.stream ().forEach (n -> {
            System.out.print (n + " ");// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
        });
        System.out.println ();
        numbers.stream ().forEachOrdered (n -> {
            System.out.print (n + " ");// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
        });
        System.out.println ();
        
        // parallelStream 为集合创建并行流
        numbers.parallelStream()
                .forEach(n -> {
                    System.out.print (n + " ");// 12 14 13 11 10 16 17 15 19 3 6 4 18 2 5 7 9 8 1 
                });
        System.out.println ();
        numbers.parallelStream ().forEachOrdered (n -> {
            System.out.print (n + " ");// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
        });

        System.out.println ("\r\n结束");
    }
ArrayList的序列化和反序列化的分析

从源码中可以看出来elementData是存储ArrayList数据的数组,所以序列化ArrayList数据就是序列化elementData的数组中的数据。由于数组elementData的空间有可能会有剩余,所以每次将ArrayList的数据序列化时并不需要将整个数组elementData的数组全部序列化,只需要将elementData[0..size]数据序列化就行了。所以源码中用transient 修饰了数组elementData,并自定义了writeObject方法和readObject方法,如下:

	/**
     * 将ArrayList实例保存到一个流中 (即序列化)。
     */
    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 size as capacity for behavioural compatibility with clone()
        s.writeInt(size);
        // 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();
        }
    }
    
    /** 
     * 重新创建一个ArrayList 实例(即反序列化)
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }

writeObject方法和readObject方法都用了private的修饰符修饰了,那么实际序列化时又是如何实现的呢?我们可以使用下面这段测试代码,通过debug去看看ArrayList是怎么实现自定义序列化和反序列化的

		List<String> list = new ArrayList<String>();
        list.add("hello");
        list.add("world");
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // 输出流
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            // 这个方法最终会调用ArrayList 中的writeObject() 方法
            oos.writeObject(list);
            byte[] alBytes = baos.toByteArray();
            ArrayList<String> readList = null;
            try {
            	// 输入流
                readList = (ArrayList<String>) new ObjectInputStream(
                        new ByteArrayInputStream(alBytes)).readObject();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            for (String s : readList) {
                System.out.println(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

先分析ArrayList的序列化过程:通过debug运行上面的测试代码,可以发现oos.writeObject(list);这行代码会根据传进来的ArrayList对象得到Class,然后再包装成ObjectStreamClass,在writeSerialData方法里,会调用ObjectStreamClassinvokeWriteObject方法;在invokeWriteObject方法里会调用Methodinvoke(Object obj, Object... args),通过反射调用到ArrayList里的writeObject方法。代码如下:

private void writeSerialData(Object obj, ObjectStreamClass desc)
        throws IOException {
    ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
    for (int i = 0; i < slots.length; i++) {
        ObjectStreamClass slotDesc = slots[i].desc;
		.....
		slotDesc.invokeWriteObject(obj, this);
		.....
	}
}
/**
* 调用实现 serializable 接口类的writeObject方法。
**/
void invokeWriteObject(Object obj, ObjectOutputStream out)
        throws IOException, UnsupportedOperationException {
        requireInitialized();
        if (writeObjectMethod != null) {
            try {
            	// 通过反射访问到ArrayList 中的writeObject 方法
                writeObjectMethod.invoke(obj, new Object[]{ out });
            } catch (InvocationTargetException ex) {
                Throwable th = ex.getTargetException();
                if (th instanceof IOException) {
                    throw (IOException) th;
                } else {
                    throwMiscException(th);
                }
            } catch (IllegalAccessException ex) {
                // should not occur, as access checks have been suppressed
                throw new InternalError(ex);
            }
        } else {
            throw new UnsupportedOperationException();
        }
    }

writeObjectMethod实例赋值的方式如下:

    private static Method getPrivateMethod(Class<?> cl, String name,
                                           Class<?>[] argTypes,
                                           Class<?> returnType) {
        try {
            Method meth = cl.getDeclaredMethod(name, argTypes);
            // 设置private 方法可以访问
            meth.setAccessible(true);
            int mods = meth.getModifiers();
            return ((meth.getReturnType() == returnType) &&
                    ((mods & Modifier.STATIC) == 0) &&
                    ((mods & Modifier.PRIVATE) != 0)) ? meth : null;
        } catch (NoSuchMethodException ex) {
            return null;
        }
    }

上面是对ArrayList序列化的过程分析,反序列化的过程是调用readObject方法和序列化一样。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值