我试图从Coursera实施一个程序。程序声明是:
给定一系列非负整数a0,...,an-1,找到最大的成对乘积,即可以通过将两个不同的元素与序列相乘得到的最大整数。
我正在尝试各种方法来实施解决方案并检查哪种方法效果最佳。
我看到流仍然很快。
为什么会这样?
我受到了印象,然后找到最大的2个元素而没有排序和乘以它们将是最好的。流排序(顺序流比并行流更快)比这种方法提供更好的结果吗?
我的计划
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
public class MaxProduct {
public static void main(String[] args) {
List<Long> testList = createRandomArrayOfSize(30000000);
warmup(testList);
System.out.println("Warmup done");
Measure.meaureTime("No sorting, finding largest 2 elements and multiplying",
() -> findMaxProductByFindingLargest2Elements(new ArrayList<>(testList)));
Measure.meaureTime("Sorting, Multiplying last 2 elements",
() -> findMaxProductUsingSorting(new ArrayList<>(testList)));
Measure.meaureTime("Sorting using streams, Multiplying last 2 elements",
() -> findMaxProductUsingStreamSorting(new ArrayList<>(testList)));
Measure.meaureTime("Parallel sorting using streams, Multiplying last 2 elements by reduction",
() -> findMaxProductReducingParallelStream(new ArrayList<>(testList)));
}
public static long findMaxProductByFindingLargest2Elements(List<Long> list) {
long largest = 0;
long secondlargest = 0;
for (Long no : list) {
if (no > largest) {
secondlargest = largest;
largest = no;
}
}
return largest * secondlargest;
}
public static long findMaxProductUsingSorting(List<Long> list) {
list.sort(Comparator.naturalOrder());
return list.get(list.size() - 1) * list.get(list.size() - 2);
}
public static long findMaxProductUsingStreamSorting(List<Long> list) {
List<Long> collect = list.stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
return collect.get(list.size() - 1) * collect.get(list.size() - 2);
}
public static long findMaxProductReducingParallelStream(List<Long> list) {
return list.parallelStream().sorted(Comparator.reverseOrder()).limit(2).reduce((x, y) -> x * y).get();
}
private static class Measure {
private static final int NO_OF_ITERATIONS = 3;
private static void meaureTime(String description, Runnable runnable) {
long startTime = System.nanoTime();
for (int i = 0; i < NO_OF_ITERATIONS; i++) {
runnable.run();
}
long timeTakenInNanos = System.nanoTime() - startTime;
System.out.println(description + " : " + (timeTakenInNanos / 3));
}
}
private static void warmup(List<Long> testList) {
findMaxProductByFindingLargest2Elements(new ArrayList<>(testList));
findMaxProductUsingSorting(new ArrayList<>(testList));
findMaxProductUsingStreamSorting(new ArrayList<>(testList));
findMaxProductReducingParallelStream(new ArrayList<>(testList));
}
private static List<Long> createRandomArrayOfSize(int size) {
return new Random().longs(size, 1, 10000000).boxed().collect(Collectors.toList());
}
}
更新结果
没有排序,找到最大的2个元素并乘以:778547847
排序,乘以最后2个元素:13423659115
使用流进行排序,乘以最后2个元素:15518997158
使用流进行并行排序,通过缩减将最后2个元素相乘:5405983848
更新了代码
第一种方法存在错误。如果最大的no在第零个索引处,则产品将为零。需要解决这个问题。
流不快
我的测试代码出错了。修正了错误。现在按预期工作。
答案 0 :(得分:2)
不幸的是,流不一定很快。
findMaxProductUsingStreamSorting指定了一个Stream,但没有通过collect
或findFirst
实现它。它不会改变列表。因此,只有两个列表的产品才会被完成。结果也是错误的。
使用Stream,迭代的执行时间较晚,因此排序,过滤等可能会使执行变得聪明。
答案 1 :(得分:0)
您的测试存在缺陷。运行流测试的时间已经对列表进行了排序,这就是它快速的原因。