什么是总结Interger List的最快方法

时间:2017-01-21 11:36:23

标签: java list

我试图找出总结整数列表的最快方法。

首先,我创建了一个提供采样数据的方法:

public static List<Integer> getIntList(int size) {
    LinkedList<Integer> sampleList = new LinkedList<>();
    Random rand = new Random();
    rand.ints(size).forEach((num)-> sampleList.add(num));
    return sampleList;
}

然后我尝试了一些不同的方法来总结List。 首先是最糟糕的一个:

public static void sumUpWithForLoop(List<Integer> data) {
    System.out.println("For-loop:");
    long start = System.currentTimeMillis();
    int listLenght = data.size();
    int total = 0;
    for (int i = 0; i < listLenght; i++) {
        total += data.get(i);
    }
    long end = System.currentTimeMillis();
    System.out.println("Result: " + total);
    System.out.println("Duration: " + (end - start) + "ms");
}

在运行这个类之后我注意到它很慢,因为它总是使用get(index)这需要很长时间。

因此我尝试用Iterator总结List

public static void sumUpWithItterator(List<Integer> data) {
    System.out.println("Iterator:");
    long start = System.currentTimeMillis();
    int total = 0;
    for (Integer num : data) {
        total += num;
    }
    long end = System.currentTimeMillis();
    System.out.println("Result: " + total);
    System.out.println("Duration: " + (end - start) + "ms");
}

这种方法是迄今为止总结一个Integer-List的最快方法,但我仍然试图找到一个更快的方法。 我还尝试使用.stream().parallelStream()

 public static void sumUpWithNormalStream(List<Integer> data) {
    System.out.println("Stream");
    long start = System.currentTimeMillis();
    int total = data.stream().mapToInt(num -> num).sum();
    long end = System.currentTimeMillis();
    System.out.println("Result: " + total);
    System.out.println("Duration: " + (end - start) + "ms");
}
public static void sumUpWithParallelStream(List<Integer> data) {
    System.out.println("ParallelStream");
    long start = System.currentTimeMillis();
    int total = data.parallelStream().mapToInt(num->num).sum();
    long end = System.currentTimeMillis();
    System.out.println("Result: " + total);
    System.out.println("Duration: " + (end - start) + "ms");
}

正常stream几乎与迭代器一样快,而parallelStream比迭代器慢得多。我猜这是由于并行化的开销以及总结List是一个运行得非常快并且不必等待数据库操作等事情的事实。

总而言之,我对目前的方法仍然不满意,但我还没有找到更快的方法。 你有什么想法比普通的迭代器更快地总结一个List。

感谢您的支持。

2 个答案:

答案 0 :(得分:2)

使用ArrayList<Integer>代替LinkedList<integer>可能会为您带来更好的效果。而且,当这些元素在RAM上彼此相邻存储时,逐个访问元素最快,请尝试使用int[]

通常,如果要提高任何程序的性能,请尝试使用迭代和低级代码替换任何函数调用或高级代码。这应该会显着提高性能。

答案 1 :(得分:2)

在你的例子中,内存访问可能是瓶颈,因为添加整数是非常快的操作,但是访问链表的下一个元素需要两次内存访问(一个用于获取下一个节点,另一个用于访问整数值 - 类型擦除使得不可能使用未装箱的价值)。还要记住,链表可能分散在内存中,因此高速缓存未命中的概率很高。

因此,为了加快速度,您应该减少内存访问开销。从LinkedList更改为ArrayList将删除单个访问(到内存中的随机位置)。从ArrayList更改为原始数组将删除第二个,因为在这种情况下,未装箱的整数将存储在内存中。

因此基于int[]的版本应该是最快的(但不如ArrayList<Integer>版本灵活)。