Java Lambda 复用 Stream

标签 java collections lambda java-8 java-stream

我想尝试 lambda 的一些功能,并想编写一个 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:流已被操作或关闭

有了这些信息,我当然可以通过打开两个流并过滤两次来使其发挥作用

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();

但我现在的问题是关于性能的。如果我必须过滤和映射流两次,那不是很慢吗?为什么我不能在一个流上操作多次,我不明白他们为什么这样实现。 难道不可能在操作后保持流打开吗,因为每个运算符方法都会返回一个新流或单个值。

这是什么原因,还是我用错了?

最佳答案

如果您采用良好的旧方法,即使用循环,则可以使用单个循环计算最大元素和平均值。所以你只需要在这里做同样的事情。幸运的是,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 应该可以帮助您了解如何自己实现这样的操作。

关于Java Lambda 复用 Stream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24372139/

相关文章:

java - Android:通过单击按钮将一个 Activity 中的 TextView 添加到另一个 Activity 中的 ListView

java - 字符串索引越界异常 : string index out of range

python - 通过 lambda 回调在 Scrapy 蜘蛛内部传递参数

c# - 在 C# 中使用 lambda 获取嵌套列表中的特定元素

java - Java中实例变量的作用是隐藏的

java - 比较 2 个列表中的常见数字

java - 在 java 中初始化类时,创建 Collection 到 ImmutableSortedSet 的深拷贝

java - 比较不同类型的列表

java - 现有的 Java 集合支持自定义唯一性标准吗?

c# - 什么时候显式使用 delegate 关键字而不是 lambda 是更好的做法?