Java8 Stream

来源:互联网 发布:淘宝买家资料 编辑:程序博客网 时间:2024/04/28 19:48

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<Integer> integerStream = Stream.of(1, 2, 3, 5);Stream<String> stringStream = Stream.of("meituan");
      generator方法:生成一个无限长度的Stream,其元素的生成是通过给定的Supplier(这个接口可以看成一个对象的工厂,每次调用返回一个给定类型的对象)
Stream.generate(new Supplier<Double>() {    @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<E> extends Iterable<E> {    //其他方法省略    default Stream<E> 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<String> output = Arrays.asList("hi", "hello").stream().        map(String::toUpperCase).        collect(Collectors.toList());//flatMap,一对多Stream<List<Integer>> inputStream = Stream.of(        Arrays.asList(1),        Arrays.asList(2, 3),        Arrays.asList(4, 5, 6));Stream<Integer> 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,每个元素执行操作并返回一个新的 StreamStream.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等

//forEachInteger[] nums = {1, 2, 3};Stream.of(nums).forEach(num -> System.out.println(num));//toArrayInteger[] target = Stream.of(1, 2, 3).toArray(Integer[]::new);//collectStream.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/nonMatchboolean isBig = Stream.of(1, 100, 1000).allMatch(n -> n > 99);

4.自己生成流

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

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






0 0