我有这个LinkedHashMap:
myMap = {
0 => 10,
1 => 6,
2 => 28,
...
}
int limit = 15;
我想要使用流做的是对(按顺序)求和地图值,并在达到限制时停止,并返回地图中的相应索引(在本例中为0)。 流有优雅的方式吗?
答案 0 :(得分:1)
你总结到这样的限制
myMap.values().reduce(0, (a, b) -> a+b > limit ? a : a + b);
答案 1 :(得分:1)
可以通过我的免费StreamEx库扩展标准Stream API,但即使使用库也不是很优雅:
EntryStream.of(myMap) // like myMap.entrySet().stream()
.prefix(
(e1, e2) -> new AbstractMap.SimpleEntry<>(e2.getKey(), e1.getValue() + e2.getValue()))
.takeWhile(e -> e.getValue() < limit)
.reduce((a, b) -> b)
.ifPresent(System.out::println);
这里我们使用两个特殊的StreamEx操作。一个是prefix
,它懒惰地计算运行前缀(如Haskell中的scanl
)。这里有两个条目,我们选择后一个的键和它们的值的总和,创建一个新条目。接下来,我们使用takeWhile
(也将出现在Java 9标准Stream API中)在值超出限制时立即停止。最后,我们减少到最后找到的元素并打印它,如果它存在,所以我们不仅索引,而且还打印最终总和(如果你只需要索引,添加.map(Entry::getKey)
步骤。)
虽然这样的解决方案是无用的FP-ish我不推荐它一般,因为它不是非常有效并且产生垃圾(中间条目和盒装整数),更不用说外部库依赖。使用普通旧循环。它高效且易于理解:
int sum = 0;
Integer lastKey = null;
for(Map.Entry<Integer, Integer> e : myMap.entrySet()) {
sum+=e.getValue();
if(sum >= limit) break;
lastKey = e.getKey();
}
if(lastKey != null) {
System.out.println(lastKey);
}