美文网首页编程杂货铺
Java8新特性Stream

Java8新特性Stream

作者: 会动的木头疙瘩儿 | 来源:发表于2018-10-10 14:52 被阅读4次

声明转载自:http://www.importnew.com/11908.html#streams

Stream API极大简化了集合框架的处理:

package com.spring.nahong.swagger2.swaggerdoc.test;

import java.util.Arrays;
import java.util.Collection;

public class Streams  {
    private enum Status {
        OPEN, CLOSED
    }


    public static void main(String[] args) {
        final Collection< Task > tasks = Arrays.asList(
                new Task( Status.OPEN, 5 ),
                new Task( Status.OPEN, 13 ),
                new Task( Status.CLOSED, 8 )
        );

        final long totalPointsOfOpenTasks = tasks
                .stream()
                .filter( task -> task.getStatus() == Status.OPEN )
                .mapToInt( Task::getPoints )
                .sum();

        System.out.println( "Total points: " + totalPointsOfOpenTasks );
    }


    private static final class Task {
        private final Status status;
        private final Integer points;

        Task( final Status status, final Integer points ) {
            this.status = status;
            this.points = points;
        }

        public Integer getPoints() {
            return points;
        }

        public Status getStatus() {
            return status;
        }

        @Override
        public String toString() {
            return String.format( "[%s, %d]", status, points );
        }
    }
}

上面创建Task类,里面有状态status和分类points
Task类有一个分数的概念(或者说是伪复杂度),其次是还有一个值可以为OPEN或CLOSED的状态.让我们引入一个Task的小集合作为演示例子:

final Collection< Task > tasks = Arrays.asList(
                new Task( Status.OPEN, 5 ),
                new Task( Status.OPEN, 13 ),
                new Task( Status.CLOSED, 8 )
        );

我们下面要讨论的第一个问题是所有状态为OPEN的任务一共有多少分数?在Java 8以前,一般的解决方式用foreach循环,但是在Java 8里面我们可以使用stream:一串支持连续、并行聚集操作的元素。

final long totalPointsOfOpenTasks = tasks
                .stream()
                .filter( task -> task.getStatus() == Status.OPEN )
                .mapToInt( Task::getPoints )
                .sum();

        System.out.println( "Total points: " + totalPointsOfOpenTasks );

执行程序控制台打印结果:

Total points: 18

这里有几个注意事项。第一,task集合被转换化为其相应的stream表示。然后,filter操作过滤掉状态为CLOSED的task。下一步,mapToInt操作通过Task::getPoints这种方式调用每个task实例的getPoints方法把Task的stream转化为Integer的stream。最后,用sum函数把所有的分数加起来,得到最终的结果。

在继续讲解下面的例子之前,关于stream有一些需要注意的地方(详情在这里).stream操作被分成了中间操作与最终操作这两种。

中间操作返回一个新的stream对象。中间操作总是采用惰性求值方式,运行一个像filter这样的中间操作实际上没有进行任何过滤,相反它在遍历元素时会产生了一个新的stream对象,这个新的stream对象包含原始stream
中符合给定谓词的所有元素。

像forEach、sum这样的最终操作可能直接遍历stream,产生一个结果或副作用。当最终操作执行结束之后,stream管道被认为已经被消耗了,没有可能再被使用了。在大多数情况下,最终操作都是采用及早求值方式,及早完成底层数据源的遍历。

stream另一个有价值的地方是能够原生支持并行处理。让我们来看看这个算task分数和的例子。

public static void main(String[] args) {

        final Collection< Task > tasks = Arrays.asList(
                new Task( Status.OPEN, 5 ),
                new Task( Status.OPEN, 13 ),
                new Task( Status.CLOSED, 8 )
        );

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

这个例子和第一个例子很相似,但这个例子的不同之处在于这个程序是并行运行的,其次使用reduce方法来算最终的结果。
下面是这个例子在控制台的输出:

Total points (all tasks): 26.0

经常会有这样的需求:我们需要按照某种准则来对集合中的元素进行分组。Stream也可以处理这样的需求,下面是一个例子:

public static void main(String[] args) {

        final Collection< Task > tasks = Arrays.asList(
                new Task( Status.OPEN, 5 ),
                new Task( Status.OPEN, 13 ),
                new Task( Status.CLOSED, 8 )
        );

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

控制台输出:

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

让我们来计算整个集合中每个task分数(或权重)的平均值来结束task的例子

public static void main(String[] args) {

        final Collection< Task > tasks = Arrays.asList(
                new Task( Status.OPEN, 5 ),
                new Task( Status.OPEN, 13 ),
                new Task( Status.CLOSED, 8 )
        );

        final double totalPoints = tasks
                .stream()
                .parallel()
                .map( task -> task.getPoints() ) // or map( Task::getPoints )
                .reduce( 0, Integer::sum );


        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%]

最后,就像前面提到的,Stream API不仅仅处理Java集合框架。像从文本文件中逐行读取数据这样典型的I/O操作也很适合用Stream API来处理。下面用一个例子来应证这一点。

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流

    Stream流 java8新特性 Stream定义 A sequence of elements supporti...

  • Stream API

    Stream 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!! Stream API Java...

  • java 8 stream 流详细教程

    1 基本特性 Java8的API中添加了一个新的特性: 流,即stream。stream是将数组或者集合的元素视为...

  • JAVA8新特性:Stream与Lambda表达式

    一、Stream学习 在学习lambda表达式之前,我们需要先了解Stream这个java8的新特性。 Strea...

  • Java8新特性系列(流性能)

    上期介绍了Java8中Stream的新特性,本期我们将测试下stream与parallelStream的性能以及应...

  • java8新特性

    java8新特性 原创者:文思 一、特性简介 速度更快 代码更少,增加了Lambda 强大的Stream API ...

  • 03_Java8_Lamda表达式学习

    Java8 的新特性:Lambda表达式、强大的 Stream API、全新时间日期 API、Concurrent...

  • parallelStream使用不当引发的血案

    Stream简洁 众所周知,java8的新特性中出了lambda表达式之外最受人关注的还有stream一系列的ap...

  • Java8新特性Stream

    声明转载自:http://www.importnew.com/11908.html#streams Stream ...

  • JAVA8新特性:Stream

    1.筛选与切片: 测试结果 2.映射: 接受lambda,作用到每一个元素,并得到新值1.大小写转换 2.提取每个...

网友评论

    本文标题:Java8新特性Stream

    本文链接:https://www.haomeiwen.com/subject/zdypaftx.html