`
gcq04552015
  • 浏览: 457313 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

遍历ArrayList,Iterator和for循环哪个更快

 
阅读更多
Iterator 主要性能开销在next方法体,其一:对记录集进行检测,如果在迭代的过程中,记录集有被修改,会抛出异常;其二:next方法体内有try...catch方法体,这也会影响性能,JVM不能对try...catch块内的代码进行优化。
而for因为不管数据被中途修改,也不进行异常处理,所以当然快啦



详细:

ArrayList的iterator是在AbstractList里面的
它的next方法如下:

Java code
    public E next() {
            checkForComodification();
        try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
        } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
        }
    }


而其中的get为:
Java code
    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        return l.get(index+offset);
    }


看到这个l.get(index+offset)了没?这个l就是AbstractList本身
所以,最终调用的是ArrayList的get:
Java code
    public E get(int index) {
    RangeCheck(index);

    return (E) elementData[index];
    }


总结:对ArrayList而言,for里面的get比较单纯,而iterator的next多了checkForComodification,rangeCheck等,所以变慢了。




引用 5 楼 quqiujie 的回复:
把arrayList改为LinkedList,就知道结果了



LinkedList又是另外一个话题了,不过LZ的程序千万别不动脑筋的把ArrayList变成LinkedList呀。
LZ的程序的for循环,如果用LinkedList的话,慢死你没商量!
理由很简单LinkedList的get(int index)是调用AbstractSequentialList的public E get(int index):
Java code
    public E get(int index) {
        try {
            return listIterator(index).next();
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }


而listIterator(index)的最终是要调LinkedList的ListItr(int index):
Java code
    ListItr(int index) {
        if (index < 0 || index > size)
        throw new IndexOutOfBoundsException("Index: "+index+
                            ", Size: "+size);
        if (index < (size >> 1)) {
        next = header.next;
        for (nextIndex=0; nextIndex<index; nextIndex++)
            next = next.next;
        } else {
        next = header;
        for (nextIndex=size; nextIndex>index; nextIndex--)
            next = next.previous;
        }
    }


现在,知道有多慢了吧?一个for循环,从0知道到index,也就是说LZ的程序如果用LinkedList做for循环调get(int index)方法的话,算法复杂度为O(n*n)!

然而,LinkedList的Iterator却是个好东西。它的next为:
Java code
    public E next() {
        checkForComodification();
        if (nextIndex == size)
        throw new NoSuchElementException();

        lastReturned = next;
        next = next.next;
        nextIndex++;
        return lastReturned.element;
    }




简单吧?就一个next = next.next,全搞定!链表就是这个好,顺序遍历的时候很快,其实我觉得要比上面那个ArrayList的get(return elementData[index])要快。C里面也许数组挺快,但是Java里面,这个elementData是个Object数组,要求offset应该不是就一个乘法加一个加法那么简单吧?就算是一个乘法加一个加法,链表LinkedList就一个next的赋值(next是Entry)应该更快。



Iterator为什么产生?

ArrayList 和 LinkedList 是两个区别很大的集合, 没必要一起比嘛

Iterator 是集合提供的一个通用接口, 用来遍历集合元素的。在Collection下的集合都可以使用这个接口来遍历

提醒一下:用Iterator 迭代, 不是一样用了循环的嘛。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics