给出以下代码
List<Double> radia = Arrays.asList(1.0, 1.3, 1.6, 1.9);
List<Ball> listOfBalls = new ArrayList<>();
radia.forEach(radius -> listOfBalls.add(new Ball(radius)));
listOfBalls.stream().map(b -> b.getVolume())
.filter(d -> d>10)
.forEach(d -> pprint(d));
如何保留最后一个forEach中正在打印的Ball? 我希望能够打印像
这样的东西"Ball with radius " b.getRadius() + " has volume" + d
答案 0 :(得分:3)
由于lambda无法分配到其范围之外的变量,因此您必须使用较高范围内的对象才能存储结果。
注意,这不是lambdas或流API的预期用途。如果您要查找单个最终结果,则应使用findFirst
或findAny
,如下所示:
listOfBalls.stream().map(Ball::getVolume)
.filter(d -> d>10)
.findFirst();
如果您正在寻找List
Balls
,请使用Collectors.toList()
,如下所示:
List<Ball> result = listOfBalls.stream().map(Ball::getVolume)
.filter(d -> d>10)
.collect(Collectors.toList());
此时,您可以遍历列表并输出您想要的内容。流在运行时消耗,这意味着在您调用forEach
后不能使用它们,列表不受此限制的约束。
答案 1 :(得分:0)
您可以通过不将每个Ball
映射到其音量来实现您想要的效果,然后根据需要进行过滤:
listOfBalls.stream()
.filter(b -> b.getVolume() > 10)
.forEach(b -> System.out.println(
"Ball with radius " + b.getRadius() + " has volume " + b.getVolume()));
根据{{3}} 编辑:
如果不希望两次调用Ball.getVolume
方法(由于昂贵的计算或数据库访问),您可以将该方法的结果与相应的Ball
实例一起传递给流。如果您使用的是Java 9 +:
listOfBalls.stream()
.map(b -> Map.entry(b, b.getVolume())) // perform expensive call here
.filter(e -> e.getValue() > 10)
.forEach(e -> System.out.println(
"Ball with radius " + e.getKey().getRadius() + " has volume " + b.getValue()));
如果您使用的是Java 8,则可以使用new AbstractMap.SimpleEntry<>(...)
代替Map.entry(...)
。