我有这样的LinkedHashMap:Java8总结与流的限制
myMap = {
0 => 10,
1 => 6,
2 => 28,
...
}
int limit = 15;
我会想使用流是总结(按顺序)的映射值做,并停止达到限制时,并返回地图中的相应索引(在这种情况下为0)。 有没有一个优雅的方式与流?
我有这样的LinkedHashMap:Java8总结与流的限制
myMap = {
0 => 10,
1 => 6,
2 => 28,
...
}
int limit = 15;
我会想使用流是总结(按顺序)的映射值做,并停止达到限制时,并返回地图中的相应索引(在这种情况下为0)。 有没有一个优雅的方式与流?
你可以总结到了一个极限这样
myMap.values().reduce(0, (a, b) -> a+b > limit ? a : a + b);
它通过延伸的标准流API我免费StreamEx库的可能,但即使与库它不是很优雅:
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我不会推荐它在一般情况下,因为它不是很有效,并产生垃圾(中间条目和盒装整数),更不用说外部库依赖。使用普通的旧for循环。这是有效的和易于理解的:
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);
}
我没有看到任何。总是有办法做到这一点,但是与简单的循环相比,这将是人为设计的。 Justa问题,为什么你使用LinkedHashMap而不是List,因为你的键是索引? –
@Andrea,java 8没有'takeWhile'操作来执行某些操作,例如*“在达到限制时停止”* – Andrew
应该返回什么内容,例如,示例中的5和100? – Tunaki