Java中的流是在使用lambda表达式的声明性操作管道中并行或顺序地处理(映射、筛选、转换、故约和集合)元素序列。Java 8中引入流机制,使用lambda表达式从功能上改变处理大量数据的方式,来代替传统的命令式方式。
Stream接口不像其它并发类提供许多方法来监视其状态,只有peek()方法用来输出正在处理的元素日志消息。本节将学习如何使用这个方法输出关于流的信息。
准备工作
本范例通过Eclipse开发工具实现。如果使用诸如NetBeans的开发工具,打开并创建一个新的Java项目。
实现过程
通过如下步骤实现范例:
-
创建包含main()方法的Main类,声明两个私有变量,名为counter的AtomicInteger和名为random的Random对象:
public class Main { public static void main(String[] args) { AtomicLong counter = new AtomicLong(0); Random random=new Random();
-
创建包含1000个随机double数字的流,这是一个顺序流,需要使用parallel()方法使其并行化,然后使用peek()方法增加counter变量值,且输出信息到控制台。使用count()方法计算数组中的元素数量,将结果存储到整数变量中。输出存储在counter变量中的值和count()方法返回的值到控制台:
long streamCounter = random.doubles(1000).parallel().peek( number -> { long actual=counter.incrementAndGet(); System.out.printf("%d - %f\n", actual, number); }).count(); System.out.printf("Counter: %d\n", counter.get()); System.out.printf("Stream Counter: %d\n", streamCounter);
-
现在设置counter属性值为0,创建另一个包含1000个随机double数的流,然后使用parallel()方法将它转换成并行流,接着使用peek()方法增加counter变量值且输出信息到控制台。最后,使用forEach()方法输出所有数字和counter变量值到控制台:
counter.set(0); random.doubles(1000).parallel().peek(number -> { long actual=counter.incrementAndGet(); System.out.printf("Peek: %d - %f\n", actual,number); }).forEach( number -> { System.out.printf("For Each: %f\n", number); }); System.out.printf("Counter: %d\n", counter.get()); } }
工作原理
本范例中,在两种不同的情况下使用peek()方法计算通过此操作的流元素数量,并输出信息到控制台。
在第六章“并行和响应式流“中描述到,Stream包括源、零或者多个中间操作和最终操作。在第一种情况中,最终操作是count()方法,此方法不需要处理元素来计算返回值,所以peek()方法永不会被执行,即在控制台上看不到任何peek方法的信息,couter变量值将是0。
第二种情况的最终操作是forEach()方法,流的所有元素都将被处理。控制台将会输出peek()和forEach()方法 信息,counter变量的最终值将是1000。
peek()方法是流的中间操作,与所有中间操作一样,它们是懒执行的且只处理必要的元素。这也是此方法为什么不会在第一种情况中执行的原因。
更多关注
- 第六章“并行和响应式流”中的“创建不同来源的流”、“归约流元素”和“集合流元素”小节