zoukankan      html  css  js  c++  java
  • java8的Streams

    首先看一个问题:在这个task集合中一共有多少个OPEN状态的?计算出它们的points属性和。在Java 8之前,要解决这个问题,则需要使用foreach循环遍历task集合;但是在Java 8中可以利用steams解决:包括一系列元素的列表,并且支持顺序和并行处理。

    // Calculate total points of all active tasks using sum()
    final long totalPointsOfOpenTasks = tasks
        .stream()
        .filter( task -> task.getStatus() == Status.OPEN )
        .mapToInt( Task::getPoints )
        .sum();
    
    System.out.println( "Total points: " + totalPointsOfOpenTasks );

    这里有很多知识点值得说。首先,tasks集合被转换成steam表示;其次,在steam上的filter操作会过滤掉所有CLOSEDtask;第三,mapToInt操作基于tasks集合中的每个task实例的Task::getPoints方法将task流转换成Integer集合;最后,通过sum方法计算总和,得出最后的结果。

    在学习下一个例子之前,还需要记住一些steams(点此更多细节)的知识点。Steam之上的操作可分为中间操作和晚期操作。

    中间操作会返回一个新的steam——执行一个中间操作(例如filter)并不会执行实际的过滤操作,而是创建一个新的steam,并将原steam中符合条件的元素放入新创建的steam。

    晚期操作(例如forEach或者sum),会遍历steam并得出结果或者附带结果;在执行晚期操作之后,steam处理线已经处理完毕,就不能使用了。在几乎所有情况下,晚期操作都是立刻对steam进行遍历。

    steam的另一个价值是创造性地支持并行处理(parallel processing)。对于上述的tasks集合,我们可以用下面的代码计算所有task的points之和:

    // Calculate total points of all tasks
    final double totalPoints = tasks
       .stream()
       .parallel()
       .map( task -> task.getPoints() ) // or map( Task::getPoints ) 
       .reduce( 0, Integer::sum );
    
    System.out.println( "Total points (all tasks): " + totalPoints );

    这里我们使用parallel方法并行处理所有的task,并使用reduce方法计算最终的结果。控制台输出如下:

    对于一个集合,经常需要根据某些条件对其中的元素分组。利用steam提供的API可以很快完成这类任务,代码如下:

    // Group tasks by their status
    final Map< Status, List< Task > > map = tasks
        .stream()
        .collect( Collectors.groupingBy( Task::getStatus ) );
    System.out.println( map );

    控制台的输出如下:

    {CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]}

    最后一个关于tasks集合的例子问题是:如何计算集合中每个任务的点数在集合中所占的比重,具体处理的代码如下:

    // Calculate the weight of each tasks (as percent of total points) 
    final Collection< String > result = tasks
        .stream()                                        // Stream< String >
        .mapToInt( Task::getPoints )                     // IntStream
        .asLongStream()                                  // LongStream
        .mapToDouble( points -> points / totalPoints )   // DoubleStream
        .boxed()                                         // Stream< Double >
        .mapToLong( weigth -> ( long )( weigth * 100 ) ) // LongStream
        .mapToObj( percentage -> percentage + "%" )      // Stream< String> 
        .collect( Collectors.toList() );                 // List< String > 
    
    System.out.println( result );

    控制台输出结果如下:

    [19%, 50%, 30%]

    最后,正如之前所说,Steam API不仅可以作用于Java集合,传统的IO操作(从文件或者网络一行一行得读取数据)可以受益于steam处理,这里有一个小例子:

    final Path path = new File( filename ).toPath();
    try( Stream< String > lines = Files.lines( path, StandardCharsets.UTF_8 ) ) {
        lines.onClose( () -> System.out.println("Done!") ).forEach( System.out::println );
    }

    Stream的方法onClose() 返回一个等价的有额外句柄的Stream,当Stream的close()方法被调用的时候这个句柄会被执行。Stream API、Lambda表达式还有接口默认方法和静态方法支持的方法引用,是Java 8对软件开发的现代范式的响应。

  • 相关阅读:
    使用NPOI导出Excel 并设置Excel样式(合并单元格、行高、宽度、字体、边框、位置)...
    DevExpress GridView 单元格进度条
    c# groupBox 带标题边框,标题居中,重写控件
    COCO数据集下载断断续续后unzip无法解压
    SSD_论文+代码(pytorch)
    开始机器学习
    收藏 —— KVM网络虚拟化
    收藏 —— 教你阅读Python开源项目
    收藏 —— 活动目录讲解
    系统计划 Cron作业 为什么/etc/crontab /etc/cron.d /etc/cron.* 那么多的定义方式????
  • 原文地址:https://www.cnblogs.com/coder-lzh/p/9747040.html
Copyright © 2011-2022 走看看