`

java ArrayList源码 下

阅读更多

版本 jdk-7u71-windows-x64

 

JavaSE7 ArrayList源码上:http://flyouwith.iteye.com/blog/2166890  

 

	/**
	 * 从这个列表中移除所有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++)
				//*****注意这种在集合中删除n多元素的逻辑*****
				if (c.contains(elementData[r]) == complement)
					elementData[w++] = elementData[r];
		} finally {
			if (r != size) {
				System.arraycopy(elementData, r, elementData, w, size - r);
				w += size - r;
			}
			if (w != size) {
				// 明确让GC做它的工作
				for (int i = w; i < size; i++)
					elementData[i] = null;
				modCount += size - w;
				size = w;
				modified = true;
			}
		}
		return modified;
	}

    /**
     * 私有,不知道留着干嘛用的
     * 序列化ArrayList的实例
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        int expectedModCount = modCount;
        s.defaultWriteObject();
        s.writeInt(size);

        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;
        s.defaultReadObject();
        s.readInt(); 
        if (size > 0) {
            ensureCapacityInternal(size);
            Object[] a = elementData;
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }

    /**
     * 返回一个指向数组索引index处的ListIterator
     */
    public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index);
        
        return new ListItr(index);
    }

    /**
     * 返回一个指向数组起始处的ListIterator
     */
    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }

    /**
     * 返回一个指向数组起始处的iterator
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * 此为内部类,是ArrayList,iterator的具体实现
     */
    private class Itr implements Iterator<E> {
        int cursor;       // 下一个元素的索引,初始0
        int lastRet = -1; // 当前返回元素的索引,初始-1,没有可返回的元素
        //这个元素的作用出来了,在进行迭代的时候
        //如果有改变modCount值的方法执行,那么就会抛出异常
        //看这个内部类的最后一个方法
        int expectedModCount = modCount; 

        //判断下一个元素是否存在,返回false循环退出
        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; //在next()取值时 ,计算下一个索引
            return (E) elementData[lastRet = i];
        }

        //删除lastRet索引处元素
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
            	//上面介绍过的方法
                ArrayList.this.remove(lastRet);
                //上面方法执行后,cursor下一个索引位置前移
                cursor = lastRet;
                //一次next()只允许删除一次元素
                lastRet = -1;
                //因为执行删除modCount值改变。重新赋值
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
        //检核
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

    /**
     * 内部类,是ArrayList,ListIterator的具体实现
     * 注意这里继承了上面的向后迭代器
     * 所以这个迭代器可以向前和向后迭代
     */
    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();
            }
        }
    }

 

 

就上面的listIterator写个小程序看看

	public static void main(String[] args) throws IOException{
		//初始化
		ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","d","e"));
		//从2位置("d")开始迭代
		ListIterator<String> iter = list.listIterator(2);
		//cursor=2
		iter.add("c");//在d位置插入c,d、e后移一位
		//cursor=3
		if(iter.hasPrevious()){  //向前迭代 
			//cursor=3
			System.err.println(iter.previous());//elementData[2]
			//cursor=2
		}
		if(iter.hasNext()){      //向后迭代 
			//cursor=2
			System.err.println(iter.next());   //elementData[2]
			//cursor=3
		}
		if(iter.hasPrevious()){  //向前迭代
			//cursor=3
			System.err.println(iter.previous());//elementData[2]
			//cursor=2
		}
		if(iter.hasNext()){      //向后迭代 
			//cursor=2
			System.err.println(iter.next());   //elementData[2]
			//cursor=3
		}
		while(iter.hasNext()){
			System.out.println(iter.next());
		}
	}

      输出:

             c
             c     
             c
             c
             d
             e

继续源码

   /**
     * 截取一段数据,生成一个新的List。
     * 如果原数组(列表)太大,可以截取出一段来进行操作。
     * 其实就是对原数组(列表)的某一段的操作,改变哪一个另一个都会改变
     */
    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 + ")");
    }

    /**
     * 继承了AbstractList 所以具有所有List的功能
     * 但是操作的依然是源数据
     * 下面方法基本都是通过操作索引大小来调用外部类的方法操作源数组
     * 没什么意思。。不介绍了
     */
    private class SubList extends AbstractList<E> implements RandomAccess {
        private final AbstractList<E> parent;
        private final int parentOffset;
        private final int offset;
        int size;

        SubList(AbstractList<E> parent,
                int offset, int fromIndex, int toIndex) {
            this.parent = parent;
            this.parentOffset = fromIndex;
            this.offset = offset + fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = ArrayList.this.modCount;
        }

        public E set(int index, E e) {
            rangeCheck(index);
            checkForComodification();
            E oldValue = ArrayList.this.elementData(offset + index);
            ArrayList.this.elementData[offset + index] = e;
            return oldValue;
        }

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

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

        public void add(int index, E e) {
            rangeCheckForAdd(index);
            checkForComodification();
            parent.add(parentOffset + index, e);
            this.modCount = parent.modCount;
            this.size++;
        }

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

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

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

        public boolean addAll(int index, Collection<? extends E> c) {
            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;
        }

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

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

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

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

                @SuppressWarnings("unchecked")
                public E next() {
                    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)];
                }

                public boolean hasPrevious() {
                    return cursor != 0;
                }

                @SuppressWarnings("unchecked")
                public E previous() {
                    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)];
                }

                public int nextIndex() {
                    return cursor;
                }

                public int previousIndex() {
                    return cursor - 1;
                }

                public void remove() {
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

                    try {
                        SubList.this.remove(lastRet);
                        cursor = lastRet;
                        lastRet = -1;
                        expectedModCount = ArrayList.this.modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

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

                    try {
                        ArrayList.this.set(offset + lastRet, e);
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

                public void add(E e) {
                    checkForComodification();

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

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

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

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

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

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

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

 

 

补充一下 ArrayList 实现了一个RandomAccess标记接口

        如果集合类是RandomAccess的实现,则尽量用for(int i = 0; i < size; i++) 来遍历而不要用Iterator迭代器来遍历,在效率上要差一些。反过来,如果ListSequence List,则最好用迭代器来进行迭代。

        在对List特别是Huge size的List的遍历算法中,要尽量来判断是属于RandomAccess还是Sequence List,因为适合RandomAccess List的遍历算法,用在Sequence List上就差别很大。

 

 

 

1
2
分享到:
评论
2 楼 shuizhaosi888 2014-12-30  
string2020 写道
RandomAccess 是干啥的

你可以参考一下http://jianchen.iteye.com/blog/291047
谈一下我自己的看法:
因为ArrayList底层实现就是一个数组,如果用Iterator进行迭代的话,我们根据源码也能看到,它附加了很多操作(比如各种数组越界的检核)然后才通过数组下标返回数据,如果用for循环就直接返回下标数据了,这样的话我就对该容器添加一个标记RandomAccess来告诉使用人员,这个容器适合用for循环进行读取数据。
而LinkedList的数据结构是双向链表,跟ArrayList完全不是一回事。他每一个元素并没有记录下标,而是记录上一个和下一个元素,所以用Iterator会比较快。
1 楼 string2020 2014-12-29  
RandomAccess 是干啥的

相关推荐

Global site tag (gtag.js) - Google Analytics