我想尝试lambdas的一些功能,并希望编写过滤器ArrayList并使用IntStream的方法计算数组列表的平均值和最大值。
我的第一个想法是过滤ArrayList,保存流,然后使用方法计算:
ArrayList<Integer> arr = new ArrayList<>();
arr.add(5);
arr.add(7);
arr.add(11);
IntStream s = arr.stream().filter(i -> i < 10).mapToInt(i -> (int)i);
int maxBelowTen = s.max().getAsInt();
double avgBelowTen = s.average().getAsDouble();
System.out.println("Maximum below ten: " + maxBelowTen);
System.out.println("Average below ten: " + avgBelowTen);
但是,这将引发Java . lang . illegalstateexception:stream已经被操作或关闭
有了这些信息,我当然把它带到工作中,打开两个流,过滤两次
int maxBelowTen = arr.stream().filter(i -> i < 10).mapToInt(i -> (int) i).max().getAsInt();
double avgBelowTen = arr.stream().filter(i -> i < 10).mapToInt(i -> (int) i).average().getAsDouble();
但我现在的问题是关于性能。如果我必须过滤和映射流两次,这不是很慢吗。为什么我不能在一个流上操作不止一次,我不明白他们为什么这样实现它。因为每个操作符方法都返回一个新的流或一个值,所以在一个操作之后,不可能让流保持打开状态吗。
这是什么原因,或者我只是用错了?
如果您想“保存”中间流操作的结果,您可以这样做;您只需要显式地这样做:您必须执行arr.stream(). filter(i-
流不是数据结构,它们是尚未运行的未决计算,可能会以非标准方式将未来的操作合并在一起。如果您想将中间结果存储在适当的数据结构中,您必须自己动手。
如果你用一种很好的老方法,通过使用一个循环,你会用一个循环计算最大元素和平均值。所以你只需要在这里做同样的事情。幸运的是,流API可以为您做到这一点:
IntStream s = arr.stream().mapToInt(i -> Integer::intValue).filter(i < 10);
IntSummaryStatistics stats = s.summaryStatistics();
double average = stats.getAverage();
int max = stats.getMax();
阅读IntSummary统计的javadoc应该可以帮助您了解如何自己实现这样的操作。