我想尝试lambdas的一些功能,并希望过滤一个ArrayList并使用IntStream的方法来计算数字ArrayList的平均值和最大值
我的第一个想法是只过滤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();
但我现在的问题是关于表现。如果我必须过滤并映射两次流,那么这不是很慢。为什么我不能在流上操作多次,我不明白为什么他们这样实现它。 在操作之后不可能打开流,因为每个操作符方法都返回一个新流或单个值。
这是什么原因,或者我只是错误使用它?
答案 0 :(得分:8)
如果你用旧的方式做到了,通过使用循环,你可以使用单个循环计算最大元素和平均值。所以你只需要在这里做同样的事情。幸运的是,Stream API可以为您完成:
IntStream s = arr.stream().mapToInt(i -> Integer::intValue).filter(i < 10);
IntSummaryStatistics stats = s.summaryStatistics();
double average = stats.getAverage();
int max = stats.getMax();
阅读IntSummaryStatistics的javadoc可以帮助您了解如何自己实现这样的操作。
答案 1 :(得分:3)
如果你想&#34;保存&#34;中间流操作的结果,你可以做到;您只需要明确地执行此操作:您必须执行arr.stream().filter(i -> i < 10).mapToInt(i -> (int) i).toArray()
,存储int[]
,然后对其执行操作。
Streams不是一种数据结构,它们是尚未运行的待处理计算,并且可能以非标准方式将未来的操作合并在一起。如果要将中间结果存储在适当的数据结构中,则必须自己完成。