Java8 学习笔记(二)——Stream流

作者: 英勇青铜5 | 来源:发表于2016-08-22 15:36 被阅读10657次

    1.简单使用

    Arrays.asList(1, 4, 2, 3, 5, 6, 7, 9, 0, 8)
          .stream()
          .sorted()// 排序
          .filter(x -> x > 3)// 过滤
          .forEach(System.out::print);
    

    运行结果:
    4,5,6,7,8,9


    • Stream(流)和InputStream/OutputStream并没有关系
    • Stream提供了很多Lambda表达式方法
    • 重点在于对数组的操作

    特点:

    1. Stream不存储数据
    2. Stream不会修改源数据,无论怎么操作源数据并不会改变
    3. Stream是单向的,不可以重复使用
    4. Stream的部分操作是延迟的
    • 只要Stream的方法返回的对象是Stream,这些方法就是延迟执行的方法
    • 延迟执行的方法,一定要等到一个迫切方法执行的时候,才会执行。一般在Stream流中,一个方法返回的不是Stream,基本就是迫切方法
    1. Stream可以执行并行操作

    2.创建Stream

    数组和集合创建Stream流方法不一样


    2.1数组创建Stream

    一般可以通过:Arrays.stream()Stream.of()

    int [] ints = new int[]{1,3,4,2,5};
    IntStream intStream= Arrays.stream(ints);
    intStream.forEach(System.out::print);
    

    运行结果:13425


    注意:不能直接把简单数据类型的数组直接作为Stream.of()的参数

    int [] ints = new int[]{1,3,4,2,5};
    Stream<int[]>stream= Stream.of(ints);
    stream.forEach(System.out::print);```
    运行结果为:
    `[I@1218025c`
    ***
    ```java
    Stream<Integer>stream2 = Stream.of(1,3,4,2,5);
    stream2.sorted().forEach(System.out::print);
    

    运行结果为:
    12345

    Stream<Integer>IntStream不是同一个对象


    2.2集合创建Stream

    集合可以通过:集合对象.stream()

    List<Integer>list = (List<Integer>) Arrays.asList(1,2,4,3,5);
    Stream<Integer>stream = list.stream();
    

    2.3创建并行Stream

    通过集合对象.parallelStream()

    List<Integer>list = (List<Integer>) Arrays.asList(1,2,4,3,5);
    Stream<Integer>stream = list.parallelStream();
    

    2.4 创建大量数据的Stream

    • 初始化一个无限重复字符串的Stream
    Stream.generate(()->"Hello World!!!").forEach(System.out::println);
    

    运行结果:
    无限打印出Hello World!!!


    • 初始化一个有限的数据的Stream

    可以通过limit()方法来限制创建数据的数量

    Stream.generate(()->"Hello World !!!").limit(5).forEach(System.out::println);
    

    运行结果:
    打印出5个Hello World!!!


    2.5创建一个规律数据的Stream

    例如,创建一个从开始1到10的数列的Stream

    Stream.iterate(1, x -> x +1).limit(10).forEach(System.out::print);
    

    运行结果:12345678910

    iterate()方法中,有两个参数,第一个为初始数据,第二个为一个Operator接口

    Stream.iterate("a", UnaryOperator.identity()).limit(10).forEach(System.out::print);
    

    运行结果:aaaaaaaaaa
    UnaryOperator.identity()自己返回自己


    3.Stream常见的操作

    • 过滤操作filter,distinct
    • 变换操作map,flatMap
    • 拆分合并流操作limit,skip,concat,peek
    • 排序操作sorted,unordered

    操作符方法内往往需要一个函数式接口

    Java8函数式接口

    3.1过滤操作

    • filter
      例:找出所有开头为大写字母的字符串
    Arrays.asList("Abc","Bc","ac","op","IQ")
            .stream()
            .filter(s->Character.isUpperCase(s.charAt(0)))
            .forEach(System.out::println);
    

    运行结果:
    Abc Bc IQ

    • distinct去除重复元素
    Arrays.asList("a","c","ac","c","a","b")
            .stream()
            .distinct()
            .forEach(System.out::println);
    

    运行结果:
    a c ac b


    3.2变换操作

    • map

    把一种类型的Stream变为另一种类型的Stream,map方法内需要一个Function接口,Function<? super String, ? extends String> mapper

    例:将字符串全部变为大写

    Arrays.asList("hdfa","adfc","aedc","yui")
          .stream()
          .map(s->s.toUpperCase()+" ,")
          .forEach(System.out::print);
    

    运行结果:
    HDFA ,ADFC ,AEDC ,YUI ,

    • flatMap

    flatMap方法也需要Function接口,只是Function接口的泛型不同,Function<? super T, ? extends Stream<? extends R>> mapper,返回的是Stream对象

    private static void flatMapStream() {
        String [] strs1 = {"a","b","c"};
        String [] strs2 = {"d","e","f"};
        String [] strs3 = {"a","g","h"};
        Arrays.asList(strs1,strs2,strs3)
              .stream()
              .flatMap(str -> Stream.of(str))
              .map(s -> s+",")
              .forEach(System.out::print);
        }
    

    运行结果:
    a,b,c,d,e,f,a,g,h,

    flatMap是把高纬度流变为低纬度流。

    flatmap变换
    str1,str2,str3作为Stream<String[]>中的元素,可以看做是二维的数组,经过flatMap变换,Stream<String[]>就变为了Stream<String>,由二维变为了一维。

    3.3拆分合并流操作

    • limit

    限制,返回 Stream 的前面 n 个元素

    Arrays.asList(1,2,3,4,5)
          .stream()
          .limit(3)
          .forEach(System.out::print);
    

    运行结果:123

    • skip

    跳过Stream前的n个元素

    Arrays.asList(1,2,3,4,5)
          .stream()
          .skip(2)
          .forEach(System.out::print);
    

    运行结果:345

    • concat

    static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
    将两个Stream合并成一个,这个方法一次只能用来合并两个Stream,不能一次多个Stream合并。

    private static void concatStream() {
        Stream<Integer>stream1=Arrays.asList(1,2,3).stream();
        Stream<String>stream2=Arrays.asList("a","b","c").stream();
        Stream.concat(stream1,stream2).forEach(System.out::print);
    }
    

    运行结果:123abc


    3.4流的排序

    sorted()方法是个元素相关的方法,和整体的数据有关系。

    • sorted(),无参方法
    Arrays.asList(3,1,4,5,2)
          .stream()
          .sorted()
          .forEach(System.out::print);
    

    运行结果:123456
    使用sorted()这个方法,要求Stream中的数据必须实现了Comparable接口

    • sorted(Comparator< ? super T > comparator)
      例:按照字符串长度进行排序
    Arrays.asList("ae","f","gqet","ertyu","zxc")
            .stream()
            .sorted((s1,s2)-> Integer.compare(s1.length(), s2.length()))
            .forEach(System.out::println);
    

    运行结果:
    f ae zxc gqet ertyu


    若两个字符串长度相同,按照字母顺序排列,可以用ComparatorthenComparaimg()

    Arrays.asList("ae", "f", "gqet", "abcd", "ertyu", "zxc")
          .stream()
          .sorted(
                   Comparator.comparing(String::length)
                             .thenComparing(String::compareTo)
                 )
          .forEach(System.out::println);
    

    运行结果:
    f ae zxc abcd gqet ertyu


    反转排序:Comparatorreversed()

    //数字
    Arrays.asList(2,3,4,1,5)
          .stream()
          .sorted(Comparator.reverseOrder())
          .forEach(System.out::print);
    //字符串
    Arrays.asList("ae", "f", "gqet", "abcd", "ertyu", "zxc")
          .stream()
          .sorted(Comparator.comparing(String::length).reversed())
          .forEach(System.out::println);
    

    如果Comparator.comparing()方法中是非方法引用的Lambda表达式,就无法直接使用.reversed()


    parallel().sorted()之后,不能直接使用forEach(),要使用forEachOrdered()。并行Stream和sorted()并不会冲突。

    使用forEach()

    Arrays.asList(1,4,5,2,3,6,8,9,7)
          .stream()
          .parallel()
          .sorted()
          .forEach(System.out::print);
    

    运行结果:378692415

    使用forEachOrdered():

    Arrays.asList(1,4,5,2,3,6,8,9,7)
          .stream()
          .parallel()
          .sorted()
          .forEachOrdered(System.out::print);
    

    运行结果:123456789


    4.Stream的结果处理

    • 遍历forEach
    • 聚合reduce
    • Optional类型
    • 收集collect

    4.1聚合reduce

    reduce()可以实现从一组数据中生成一个数据,这个方法有三种形式:

    • Optional<T> reduce(BinaryOperator<T> accumulator)
    • T reduce(T identity, BinaryOperator<T> accumulator)
    • <U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner)

    例:求累加和

    Arrays.asList(1,2,3)
          .stream()
          .reduce((sum,i)-> sum = sum+i)
          .ifPresent(System.out::print);
    

    4.2Optional

    Optional是一种容器,可以存储一些值和null。利用这个类,可以进行null的判断,能够有效的避免NullPointerException

    • get(),可以拿到Optional中的值,没有值则抛出空指针异常
    • isPresent(),有非空的值,返回true,否则返回false
    • ifPresent(),public void ifPresent(Consumer<? super T> consumer)这个方法中需要一个Consumer接口。如果有非空的值,就执行指定的Consumer的方法来处理这个非空的值;如果为空,则啥都不做

    reduce()操作返回的就是Optional


    4.3收集collect

    collect()可以将Stream流转变成集合

    List<Integer>list= Arrays.asList(1,2,3,4,5)
                             .stream()
                             .filter(i-> i>3)
                             .collect(Collectors.toList());
    list.forEach(System.out :: print);
    

    5.最后

    Java8 常见的函数式接口多看看。

    相关文章

      网友评论

        本文标题: Java8 学习笔记(二)——Stream流

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