我一直在阅读有关Java 8的文章,但还没有试用过。所以,我试着用它做一些简单的数学运算。
我正在尝试使用Java 8的新技术找到列表的平均值,总和,最大值和最小值。我想首先打印出集合中的所有数字,然后打印出average、sum、min和max。
我有:
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个不同的流?是否有一种方法可以在单个流源上执行多个并行操作?
同样,如果我要从终端/控制台获得我正在执行操作的数字,而不是它已经在集合中,该怎么办?如果我没记错的话,Java 8 In Action
描述了Collections
和Streams
之间的一个区别,Collections
已经存储了所有的元素,而Streams
不断地从源中一个元素一个元素地获取数据。这类似于用户通过控制台一个接一个地提供数字。所以,我的第二个问题是,是否有可能使数据源为流的System.in
,而不是必须先从用户输入的List
,然后转换为List
流?
一旦您有了IntStream
,调用summaryStatistics()
来获得一个IntSummaryStatistics
对象,该对象保存计数、总和、最小值、最大值和平均值。
一般来说,你可以在IntStream
上调用collect
来对流值执行你自己的自定义计算。传入一个Supplier
,提供计算的初始状态(例如sum是0
)。传入一个ObjIntConsumer
,它将当前值处理为计算状态(例如,将值添加到总和中)。传入一个BiConsumer
,合并两个独立计算的结果(用于并行计算)(例如两个总和加在一起并存储在第一个总和中)。
我知道没有将输入流转换为java.util.streams.Stream
的内置方法。最直接的方法是按照您已经建议的那样做-从输入中读取,将值存储在List
中,然后用Stream
处理它。这当然有效,但它就像一个"完整屏障"——在进一步处理之前,所有内容必须立即在内存中。
如果我要创建一些将输入从InputStream
转换为java.util.streams.Stream
的东西,我将在Spliterator.ofInt
的自定义实现中拥有某种Reader
或Scanner
,它将根据需要读取和解析int
值。然后,您可以将此自定义Spliterator.ofInt
的实例传递给StreamSupport.intStream
以创建IntStream
。