原始方案
让BigDecimal的第一个列表称为decList,将第二个Integer列表称为intList.
intList.stream().map(decList::get).collect(Collectors.toList());
这将获取第二个列表的每个值,并将其用作访问第一个列表的值的索引.然后将它们收集到新的List< BigDecimal>中.
(编辑)使用LinkedLists检查效率
这是值得思考的问题,上面的解决方案通常就足够了.
TLDR
LinkedLists唯一会损害我原始解决方案的地方是“值列表”(在本例中为BigDecimals的List)是LinkedList.
推理此测试
因为获取ArrayLists是O(1),但得到LinkedLists是O(N),可能有替代的,更快的解决方案.
我想检查一下使用Iterator的解决方案对LinkedLists来说会更快.我阅读了所有类型的Javadocs并且无法找到运行的链接列表.(.).map(..)会使用.iterator进行LinkedLists而不是调用get.因此我决定进行实际测试.
测试用例
>使用ArrayLists,使用流和映射测试上面的原始解决方案.
>使用LinkedLists,使用流和映射测试上面的原始解决方案.
>使用显式.iterator和LinkedLists测试解决方案.
>使用流和映射测试上面的原始解决方案,使用ArrayList作为索引,使用LinkedList作为值.
>使用流式和映射测试上面的原始解决方案,使用LinkedList作为索引,使用LinkedList作为值.
检测结果
ArrayList Implementation:
Duration: 70 milliseconds
Duration: 15 milliseconds
Duration: 16 milliseconds
Duration: 15 milliseconds
Duration: 15 milliseconds
Average duration: 26 milliseconds
LinkedList Implementation with Stream and Map:
Duration: 1359 milliseconds
Duration: 1387 milliseconds
Duration: 1309 milliseconds
Duration: 1302 milliseconds
Duration: 1304 milliseconds
Average duration: 1332 milliseconds
LinkedList Implementation with Iterator:
Duration: 2806 milliseconds
Duration: 2173 milliseconds
Duration: 1305 milliseconds
Duration: 1305 milliseconds
Duration: 1305 milliseconds
Average duration: 1778 milliseconds
Mix test case #4:
Duration: 1281 milliseconds
Duration: 1278 milliseconds
Duration: 1278 milliseconds
Duration: 1278 milliseconds
Duration: 1278 milliseconds
Average duration: 1278 milliseconds
Mix test case #5:
Duration: 13 milliseconds
Duration: 7 milliseconds
Duration: 7 milliseconds
Duration: 7 milliseconds
Duration: 7 milliseconds
Average duration: 8 milliseconds
结论
>由于O(N)与O(N ^ 2)的原因,我对ArrayLists的原始解决方案要比LinkedLists快得多.
>似乎流已经使用迭代器或类似的增强来解释获得效率的差异.通过测试用例2和3之间的相似性可以明显看出这一点.
> LinkedLists仅在它们包含此算法中的值时影响效率,因为使用流进行迭代器优化.注意测试用例#5与仅使用ArrayLists一样快,尽管它如何使用LinkedList作为索引.
效率测试的来源
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.math.BigDecimal;
import java.util.stream.Collectors;
import java.lang.Math;
import java.util.Iterator;
class Test {
public static void main(String[] args) {
testArrayListImplementation();
testLinkedListImplementation();
testCaseFourMixed();
testCaseFiveMixed();
}
static void testArrayListImplementation() {
List bigDecList = new ArrayList();
List ndxList = new ArrayList();
System.out.println("ArrayList Implementation:");
timeListImplementation(bigDecList, ndxList, false);
}
static void testLinkedListImplementation() {
List bigDecList = new LinkedList();
List ndxList = new LinkedList();
System.out.println("LinkedList Implementation with Stream and Map:");
timeListImplementation(bigDecList, ndxList, false);
System.out.println("LinkedList Implementation with Iterator:");
timeListImplementation(bigDecList, ndxList, true);
}
static void testCaseFourMixed() {
//Test case 4
List bigDecList = new LinkedList();
List ndxList = new ArrayList();
System.out.println("Mix test case #4:");
timeListImplementation(bigDecList, ndxList, false);
}
static void testCaseFiveMixed() {
//Test case 5
List bigDecList = new ArrayList();
List ndxList = new LinkedList();
System.out.println("Mix test case #5:");
timeListImplementation(bigDecList, ndxList, false);
}
static void timeListImplementation(List bigDecList, List ndxList, boolean useIterator) {
for (int i = 0; i < 10000; i++) {
bigDecList.add(new BigDecimal(123.4));
ndxList.add((int) (Math.random() * 1000));
}
long totalDuration = 0;
for (int linkedTrial = 0; linkedTrial < 5; linkedTrial++) {
long startTime = System.nanoTime();
for (int numComputations = 0; numComputations < 100; numComputations++) {
if (useIterator) {
Iterator ndxIter = ndxList.iterator();
List specializedList = new LinkedList();
while (ndxIter.hasNext()) {
specializedList.add(bigDecList.get(ndxIter.next()));
}
} else {
List specializedList = ndxList.stream().map(bigDecList::get).collect(Collectors.toList());
}
}
long endTime = System.nanoTime();
long duration = (endTime - startTime) / 1000000; //milliseconds
System.out.println("Duration: " + duration + " milliseconds");
totalDuration += duration;
}
System.out.println("Average duration: " + (totalDuration / 5) + " milliseconds");
}
}