自定义迭代器很慢

时间:2016-09-26 09:07:18

标签: java performance iterator

我一直试图在简单的int数组上测量自定义迭代器的性能。它真的很简单,如下所示:

class IntArrayIterator_NoCheck implements Iterator<Integer> {

    private final int[] array;
    private int counter = 0;

    public IntArrayIterator_NoCheck( int[] array ) {
        this.array = array;
    }

    @Override
    public boolean hasNext() {
        return counter < array.length;
    }

    @Override
    public Integer next() {
        return array[counter++];
    }

}

将它与ArrayList迭代器和Trove(http://trove.starlight-systems.com/)进行比较后,我发现了奇怪的结果。测试按以下方式进行:

  • 100000随机元素的列表/数组
  • 暖机
    • 10000x迭代整个集合
    • 10000x再次遍历整个集合
  • 测试
    • 10000x迭代整个集合,通过System.nanoTime和ThreadMXBean.getCurrentThreadCpuTime()进行测量

Trove TIntArrayList迭代器是运行时间为30 ms的最快的迭代器。 Java ArrayList迭代器的运行时间为85毫秒。简单的int数组上的自定义迭代器有320毫秒的运行时间!

我的自定义迭代器可怕性能的可能原因是什么?在查看ArrayList和TIntArrayList迭代器实现之后,它们要复杂得多(执行更多操作),因此我不明白为什么它更快。请问有人向我解释一下吗?

2 个答案:

答案 0 :(得分:4)

您的next方法将生成与

相同的字节码
public Integer next() {
    return Integer.valueOf(array[counter++]);
}

请注意,对于缓存值范围之外的任何int(仅保证为-128127),会创建一个新的Integer对象。

ArrayList不会发生这种情况,因为转换是在将Integer存储在列表中之前发生的。
TArrayLista custom iterator type返回基本类型int,不需要创建Integer对象。

答案 1 :(得分:3)

你有一个 Integer 的迭代器,但你使用的是 int 的数组。

因此,您在迭代时执行常量拆箱。你懂;将整数转化为整数并将其转回是一项代价高昂的操作;并且为每次迭代执行此操作 会杀死您。

每次调用 next 意味着将int装入Integer。