【问题标题】:ArrayList.ListIterator(int index) vs ArrayList.get(int index)ArrayList.ListIterator(int index) vs ArrayList.get(int index)
【发布时间】:2010-12-08 13:23:04
【问题描述】:

我想知道使用 ArrayList.ListIterator(int index - 1) 和 it.next() 与使用 ArrayList.get(int index) 相比对性能有何影响?

【问题讨论】:

  • 描述它并告诉我们。 Profiler 是唯一可以消除机器间所有可变性的东西。
  • 我认为你会输。并且在可读性方面也是如此。
  • 注意 - 实际上是 AbstractList.listIterator(int) 与 ArrayList.get(int) 相比

标签: java arraylist


【解决方案1】:

为什么要看实现...

1: List.listIterator(int)

public ListIterator<E> listIterator(final int index) {
if (index<0 || index>size())
  throw new IndexOutOfBoundsException("Index: "+index);

return new ListItr(index);
}

与

private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
    cursor = index;
}

// [...]

和

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

2: List.get(int)

public E get(int index) {
RangeCheck(index);

return (E) elementData[index];
}

应该很明显,哪个更快。关于性能影响的详细信息,我必须同意 Mike 的观点。剖析它。不管是什么原因,您都想使用这种独特的访问方法来访问一个项目(?)

【讨论】:

  • 更多的是出于好奇。不过还是谢谢。
【解决方案2】:

在我的机器上分析它,使用 10,000 个整数的 ArrayList。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

/**
 *
 * @author Michael Drogalis
 */
public class Launcher {

    public static void main(final String[] args) {
        List<Integer> sut = new ArrayList<Integer>();

        Random generator = new Random();
        for (int k = 0; k < 100000; k++) {
            sut.add(generator.nextInt(64));
        }

        testGetMethod(sut, generator);
        testIteratorMethod(sut, generator);
    }

    private static void testGetMethod(List<Integer> aList, Random aGenerator) {
        for (int k = 0; k < 100000; k++) {
            aList.get(aGenerator.nextInt(1000));
        }
    }

    private static void testIteratorMethod(List<Integer> aList, Random aGenerator) {
        for (int k = 0; k < 100000; k++) {
            Iterator iterator = aList.listIterator(Math.abs(aGenerator.nextInt(100000) - 1));
            iterator.next();
        }
    }
}

get 方法花费了 6.47 毫秒来完成 10,000 次提取。 Iterator 样式需要 18.7 毫秒才能完成 10,000 次提取。

它们相差近 3 倍。

编辑: 分析每种方法 1,000 次。以下是一些特别有趣的结果: get 需要 2403 毫秒。 迭代器耗时 3,661 毫秒。

现在是 1.5 倍。有趣...

合理的结果 - 对于我的机器。测试风险自负。

【讨论】:

  • 嗯.. 我认为最好在测试前生成索引,然后将其用于两种方法的测试。
  • 既然是随机存取的数据结构,那还重要吗?
  • nextInt 相当长的操作。所以它可以对“因素”产生影响(这只是建议)。在这种情况下,您可以对系数进行一些合理的修正。
  • @Stas Kurilin 你的观点很有趣。但是,在两次检索中,我都使用了 nextInt(),因此阻力因子同样适用于两者。也就是说,假设数字 a 的生成时间永远不会超过数字 b。
【解决方案3】:

两者都在 O(1) 中找到结果(iaw - 时间不取决于列表的大小)。因此,如果您只使用一次,您将不会注意到大小集合的差异。

但是“ListIterator”解决方案会创建额外的对象,这会浪费内存,因为我们有 get 方法,它只从后备数组中获取请求的对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    相关资源
    最近更新 更多