Java8 Stream

1.Stream的由来

      Java8引入了全新的Stream API,这里的Stream和I/O流不同,更像是Iterator的集合类,但行为和集合类不同。Stream API的引入在于弥补Java函数式编程的缺陷,可以用很少代码完成很多的功能。借助Lambda表达式,可以提高编程效率和可读性。它是对于集合功能的增强,专注于对集合对象进行各种高效,非常便利的聚合操作,或者大批量数据操作。同时提供了串行和并行两种操作,充分利用多核处理的优势,通过fork/join操作来拆分任务和加速处理过程。

2.Stream的介绍

      Stream如同一个迭代器,单向,不可重复,只可以便利一次。但是Stream支持并行,数据源可以无限。

      操作流的步骤是:获取一个数据源(source)→ 数据转换→执行操作获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。

      对Stream操作分为两种:

  • Intermediate:一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。
  • Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。

 

3.Stream的使用

      Stream的使用过程就是实现filter-reduce-map的过程,产生一个最终结果。集合类新增的Stream方法用于把集合变成Stream,然后通过filter,map等操作实现stream的变换,还有forEach来完成元素的迭代。

      3.1 Stream的创建

      3.1.1使用Stream静态方法来创建Stream

      of方法

//使用of方法
Stream integerStream = Stream.of(1, 2, 3, 5);
Stream stringStream = Stream.of("meituan");
      generator方法:生成一个无限长度的Stream,其元素的生成是通过给定的Supplier(这个接口可以看成一个对象的工厂,每次调用返回一个给定类型的对象)
Stream.generate(new Supplier() {
    @Override
    public Double get() {
        return Math.random();
    }
});
Stream.generate(() -> Math.random());
Stream.generate(Math::random);
         iterate 方法:    

Stream.iterate(1, item -> item + 1).limit(10).forEach(System.out::println);
     3.1.2通过Collection子类获取Stream对象
public interface Collection extends Iterable {
    //其他方法省略
    default Stream stream() {
        return StreamSupport.stream(spliterator(), false);
    }
}
      需要注意的是,对于基本数值类型,有三种对应的包装类型,IntStream,LongStream,DoubleStream   

      3.2 Stream的Intermidiate操作

      有map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

//map,一对一
List output = Arrays.asList("hi", "hello").stream().
        map(String::toUpperCase).
        collect(Collectors.toList());
//flatMap,一对多
Stream> inputStream = Stream.of(
        Arrays.asList(1),
        Arrays.asList(2, 3),
        Arrays.asList(4, 5, 6)
);
Stream outputStream = inputStream.
        flatMap((childList) -> childList.stream());
//filter,过滤
Integer[] sixNums = {1, 2, 3, 4, 5, 6};
Integer[] evens =
        Stream.of(sixNums).filter(n -> n%2 == 0).toArray(Integer[]::new);
//peek,每个元素执行操作并返回一个新的 Stream
Stream.of("one", "two", "three", "four")
        .filter(e -> e.length() > 3)
        .peek(e -> System.out.println("Filtered value: " + e))
        .map(String::toUpperCase)
        .peek(e -> System.out.println("Mapped value: " + e))
        .collect(Collectors.toList());
//limit,返回Stream前n个元素,skip,扔掉前n个元素
Stream.of(1, 2, 3, 4).limit(2).forEach(System.out::println);

3.3 Stream的Terminal操作

有forEach、toArray、reduce、collect、max、count、anyMatch、findFirst等

//forEach
Integer[] nums = {1, 2, 3};
Stream.of(nums).forEach(num -> System.out.println(num));
//toArray
Integer[] target = Stream.of(1, 2, 3).toArray(Integer[]::new);
//collect
Stream.of("one", "two", "three", "four")
        .filter(e -> e.length() > 3)
        .peek(e -> System.out.println("Filtered value: " + e))
        .map(String::toUpperCase)
        .peek(e -> System.out.println("Mapped value: " + e))
        .collect(Collectors.toList());
//anyMatch/allMatch/nonMatch
boolean isBig = Stream.of(1, 100, 1000).allMatch(n -> n > 99);

4.自己生成流

      通过实现 Supplier 接口,你可以自己来控制流的生成。把 Supplier 实例传递给 Stream.generate() 生成的 Stream,默认是串行(相对 parallel 而言)但无序的(相对 ordered 而言)。

Random seed = new Random();
        Supplier random = seed::nextInt;
        Stream.generate(random).limit(10).forEach(System.out::println);
//Another way
IntStream.generate(() -> (int) (System.nanoTime() % 100)).
        limit(10).forEach(System.out::println);






你可能感兴趣的:(Java8 Stream)