저는 Coursera에서 프로그램을 구현하려고했습니다. 프로그램 문은 다음과 같습니다.Whys 스트림이 너무 빠름
음수가 아닌 정수 a0, ..., an-1의 시퀀스가 주어지면 최대 pairwise 곱, 즉 시퀀스의 두 개의 다른 요소를 곱하여 얻을 수있는 최대 정수를 찾습니다.
저는 솔루션을 구현하고 어떤 것이 가장 잘 작동 하는지를 확인하기 위해 다양한 방법을 시도하고있었습니다.
스트림이 여전히 빠릅니다.
왜 그렇게됩니까?
필자는 인상적이었습니다. 정렬하지 않고 가장 큰 두 요소를 찾고이를 곱하는 것이 가장 좋습니다. 스트림 정렬 (순차 스트림이 병렬 스트림보다 빠름)이이 방법보다 더 나은 결과를 제공합니까?
내 프로그램
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
정렬을, 마지막 두 요소를 곱 : 13423659115 개
정렬 사용하여 스트림을, 마지막 두 요소에 곱하기 : 15518997158
str을 사용한 병렬 정렬 EAMS, 감소 지난 2 개 요소를 곱 : 5405983848
는 첫 번째 방법에서 문제가 코드
에게 업데이트되었습니다. 가장 큰 no가 0 번째 인덱스에 있다면, product는 0이 될 것입니다. 그것을 고칠 필요가 있습니다.
스트림은
내 테스트 코드의 실수 빠른 아니다. 실수를 수정했습니다. 그리고 지금 예상대로 일합니다.
어떤 코스? –
https://www.coursera.org/learn/algorithmic-toolbox –
아직 몇 가지 문제가 있습니다. 1) 'warmup'을 호출 한 후리스트가 정렬됩니다. 2) 비교하는 함수가 동일한 결과를 제공하지 않습니다. 3) 마이크로 벤치 마크 작성 방법은 http://stackoverflow.com/q/504103/2568885를 참조하십시오. – binoternary