Java streams: 一个 liner 对 Int 流执行多个数字操作
Java streams: one liner to perform multiple numeric operations on Int stream
我一直在阅读有关 Java 8 的内容,但还没有尝试过。所以,我正在尝试使用它进行简单的数学运算。
我正在尝试使用 Java8 中的新技术来查找列表的平均值、总和、最大值和最小值。我想先打印出集合中的所有数字,然后再打印输出平均值、总和、最小值和最大值。
这是我的:
List<Integer> list = Arrays.asList(5,6,2,12,7,9,15,18,-1,-8);
OptionalDouble average = list.stream().mapToInt(num -> num).average();
int sum = list.stream().mapToInt(num -> num).sum();
//sort the numbers, so that min and max are found in array
int[] arr = list.stream().mapToInt(a -> {System.out.println(a); return a;}).sorted().toArray();
System.out.println("Average: " + average.getAsDouble());
System.out.println("Sum: " + sum);
System.out.println("The minimum is: " + arr[0] + ", and maximum: " + arr[arr.length-1]);
有没有办法通过一个流启动而不是创建 3 个不同的流来做到这一点?有没有办法在一个流源上执行多个并行操作?
此外,如果我要从 terminal/console 中获取正在执行操作的数字,而不是它已经在集合中,该怎么办。如果我没记错的话,Java 8 In Action
描述了 Collections
和 Streams
之间的差异之一,因为 Collections
已经存储了所有元素,而 Streams
不断获取数据从源头开始,逐个元素。因此,这类似于用户通过控制台一个一个地提供数字。所以,我的第二个问题是,是否可以将流的数据源设为 System.in
,而不必先根据用户输入制作 List
,然后再将其转换为 List
到流?
获得 IntStream
后,调用 summaryStatistics()
返回一个 IntSummaryStatistics
对象,其中包含计数、总和、最小值、最大值和平均值。
通常,您可以在 IntStream
上调用 collect
来对流值执行您自己的自定义计算。传入提供计算初始状态的 Supplier
(例如,总和为 0
)。传入一个 ObjIntConsumer
将当前值处理为计算状态(例如,将一个值添加到总和中)。传入一个 BiConsumer
合并两个单独计算的结果(用于并行计算)(例如,将两个总和相加并存储在第一个总和中)。
我知道没有将输入流转换为 java.util.streams.Stream
的内置方法。最直接的方法是按照您已经建议的那样做 - 从输入中读取,将值存储在 List
中,然后用 Stream
处理它。这当然有效,但它就像一个 "full barrier" - 在进行进一步处理之前,所有内容必须立即存储在内存中。
如果我要创建将输入从 InputStream
转换为 java.util.streams.Stream
的东西,我会在Spliterator.ofInt
的自定义实现,它将按需读取和解析 int
值。然后您可以将此自定义 Spliterator.ofInt
的实例传递给 StreamSupport.intStream
以创建 IntStream
.
我一直在阅读有关 Java 8 的内容,但还没有尝试过。所以,我正在尝试使用它进行简单的数学运算。
我正在尝试使用 Java8 中的新技术来查找列表的平均值、总和、最大值和最小值。我想先打印出集合中的所有数字,然后再打印输出平均值、总和、最小值和最大值。
这是我的:
List<Integer> list = Arrays.asList(5,6,2,12,7,9,15,18,-1,-8);
OptionalDouble average = list.stream().mapToInt(num -> num).average();
int sum = list.stream().mapToInt(num -> num).sum();
//sort the numbers, so that min and max are found in array
int[] arr = list.stream().mapToInt(a -> {System.out.println(a); return a;}).sorted().toArray();
System.out.println("Average: " + average.getAsDouble());
System.out.println("Sum: " + sum);
System.out.println("The minimum is: " + arr[0] + ", and maximum: " + arr[arr.length-1]);
有没有办法通过一个流启动而不是创建 3 个不同的流来做到这一点?有没有办法在一个流源上执行多个并行操作?
此外,如果我要从 terminal/console 中获取正在执行操作的数字,而不是它已经在集合中,该怎么办。如果我没记错的话,Java 8 In Action
描述了 Collections
和 Streams
之间的差异之一,因为 Collections
已经存储了所有元素,而 Streams
不断获取数据从源头开始,逐个元素。因此,这类似于用户通过控制台一个一个地提供数字。所以,我的第二个问题是,是否可以将流的数据源设为 System.in
,而不必先根据用户输入制作 List
,然后再将其转换为 List
到流?
获得 IntStream
后,调用 summaryStatistics()
返回一个 IntSummaryStatistics
对象,其中包含计数、总和、最小值、最大值和平均值。
通常,您可以在 IntStream
上调用 collect
来对流值执行您自己的自定义计算。传入提供计算初始状态的 Supplier
(例如,总和为 0
)。传入一个 ObjIntConsumer
将当前值处理为计算状态(例如,将一个值添加到总和中)。传入一个 BiConsumer
合并两个单独计算的结果(用于并行计算)(例如,将两个总和相加并存储在第一个总和中)。
我知道没有将输入流转换为 java.util.streams.Stream
的内置方法。最直接的方法是按照您已经建议的那样做 - 从输入中读取,将值存储在 List
中,然后用 Stream
处理它。这当然有效,但它就像一个 "full barrier" - 在进行进一步处理之前,所有内容必须立即存储在内存中。
如果我要创建将输入从 InputStream
转换为 java.util.streams.Stream
的东西,我会在Spliterator.ofInt
的自定义实现,它将按需读取和解析 int
值。然后您可以将此自定义 Spliterator.ofInt
的实例传递给 StreamSupport.intStream
以创建 IntStream
.