streamAPI汇总 (java 11)

stream Api汇总(java 11)

stream 官方Api文档
前言:stream是Java8新增的一种处理数据的方式,又称为流。类似sql的数据处理方式来集合运算和表达的处理目标数据。
作用:这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
内部逻辑:元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
设计初衷:Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

集合接口有两个方法来生成流:

  • stream() − 为集合创建串行流。
  • parallelStream() − 为集合创建并行流。

Stream API

   List<String> list = Arrays.asList("abc","abc", "", "bc", "efg", "abcd","", "jkl");
  • filter
    filter 方法用于通过设置的条件过滤出元素。
    //将list中空字符串去掉后返回一个新list:
     List<String> newList = list.stream().filter( i -> !i.isEmpty()).collect(Collectors.toList());
    
    //获取空字符串的数量:
     long count = list.stream().filter(i -> i.isEmpty()).count();
    
  • map
    接收一个有返回值的Function参数,用于映射每个元素到对应的结果。
    //将list中的每个字符串元素后面加上"a":
     List<String> newList = list.stream().map( i -> i+"a").collect(Collectors.toList());
    
  • mapToInt/mapToLong/mapToDouble
    流转换为数值流
    //转成数值流(IntStream)之后就可以进行数值统计
    //但是只有sum返回int,max和min返回OptionalInt,average返回OptionalDouble
    List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        int i = numbers.stream().mapToInt(x->x).sum();
    
    这里可以对mapToInt结果进行转换,用到如下统计结果的收集器: IntSummaryStatistics/DoubleSummaryStatistics/LongSummaryStatistics
    它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。
    //int集合相关操作:
    IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
    System.out.println("列表中最大的数 : " + stats.getMax());
    System.out.println("列表中最小的数 : " + stats.getMin());
    System.out.println("所有数之和 : " + stats.getSum());
    System.out.println("平均数 : " + stats.getAverage());
    
  • flatMap
    对流扁平化处理(比map处理的更细),如分别对List< Map>做流的操作,map的操作单位就是list,而flatMap的操作单位就是map
    //flatMap常用于合并多个集合,下面这个例子就能说明map和flatMap的区别
    	Map<String,Object> map1 = new HashMap<>(3);
        map1.put("name","张三");
        map1.put("age",2);
        map1.put("sex","女");
        Map<String,Object> map2 = new HashMap<>(3);
        map2.put("name","李四");
        map2.put("age",2);
        map2.put("sex","男");
        Map<String,Object> map3 = new HashMap<>(3);
        map3.put("name","王五");
        map3.put("age",1);
        map3.put("sex","女");
        List<Map<String,Object>> twoList = new ArrayList<>();//2岁的集合
        twoList.add(map1);
        twoList.add(map2);
        List<Map<String,Object>> nvList = new ArrayList<>();//女生的集合
        nvList.add(map1);
        nvList.add(map3);
        //map处理后去重打印后的结果是:
        //java.util.stream.ReferencePipeline$Head@7a5d012c
    	//java.util.stream.ReferencePipeline$Head@3fb6a447
    	Stream.of(twoList,nvList).map(Collection::stream).distinct().forEach(System.out::print);
    	//flatMap处理后去重打印后的结果是:
        //{name=张三, age=2, sex=女}
    	//{name=李四, age=2, sex=男}
    	//{name=王五, age=1, sex=女}
    	Stream.of(twoList,nvList).flatMap(Collection::stream).distinct().forEach(System.out::print);
    

我看到别人还有关于flatMap更复杂更细的操作,也很实用:
https://blog.csdn.net/weixin_41835612/article/details/83713891.

  • flatMapToInt/flatMapToLong/flatMapToDouble
    这个和map的相关操作mapToInt/mapToLong/mapToDouble一样,只不过操作单元更细

  • distinct
    去重

    //list是可重复的集合,用distinct实现去重
    	list.stream().distinct()
    
  • sorted
    sorted 方法用于对流进行排序。

    //对list进行正序排序:
     List<Integer> numbers = Arrays.asList(2, 1, 5, 7, 3 ,4 ,6);
     numbers.stream().sorted();
    

    排序时用Comparator可自定排序的条件

    //对list进行逆序排序:
      numbers.stream().sorted(Comparator.reverseOrder());
    //对这群person按年龄倒序:
      Person p1= new Person("张三",12,"女");
      Person p2= new Person("李四",17,"男");
      Person p3= new Person("王五",24,"女");
      Stream.of(p1,p2,p3).sorted(Comparator.comparing(Person::getAge).reversed());
    
  • peek
    都是对流的处理,map接收的是Function的参数,而peek和forEach接收的是Consumer的参数,所以map是需要返回值的,peek和forEach却没有返回值。
    然后对比peek和forEach,发现foreach会消耗掉流,即终止流操作,而peek不会。举例:

    Person p1 = new Person("zhangsan",14);
    Person p2 = new Person("lisi",18);
    //forEach执行完之后流操作就中止了
    Stream.of(p1,p2).forEach(i->i.setAge(100));
    Stream.of(p1,p2).forEach(System.out::println);
    //peek执行完之后还能再继续执行流操作(个人认为功能很鸡肋,主要是不知道这个api的设计理念和运用场景)
    Stream.of(p1,p2).peek(i->i.setAge(200)).forEach(System.out::println);
    
  • limit
    limit 方法用于获取指定数量的流。

    //取出list中前三个元素组成新list:
    List<String> newList = list.stream().limit(3).collect(Collectors.toList());
    
  • skip
    起始索引

    //将起始索引(第5个)及之后截取固定数量(2个)元素组合新集合:
    List<Integer> numbers = Arrays.asList(0,1, 2, 3, 4, 5 ,6 ,7);
    newList = numbers.stream().skip(4).limit(2).collect(Collectors.toList());//[4,5]
    
  • takeWhile/dropWhile
    从开始计算到截止计算的条件

    //从开始计算,当 n < 3 时就截止:
    Stream.of(1, 2, 3, 2, 1).takeWhile(n -> n < 3).collect(Collectors.toList());// [1, 2]
     //一旦 n < 3 不成立就开始计算:
    Stream.of(1, 2, 3, 2, 1).dropWhile(n -> n < 3).collect(Collectors.toList());// [3, 2, 1]
    
  • forEach
    Stream 提供了新的方法 ‘forEach’ 来迭代流中的每个数据,接收一个无返回值的Consumer参数。

    //循环打印list的每个元素:
    list.forEach(System.out::println);
    list.stream().forEach(System.out::println);
    
  • forEachOrdered
    这个api是用在并行流的,因为并行就意味着顺序不确定,forEachOrdered就用来保证顺序遍历

    //并行forEach遍历打印顺序是不确定的
    list.parallelStream().forEach(System.out::println);
    //并行forEachOrdered遍历打印顺序是按照list本来的顺序的
    list.parallelStream().forEachOrdered(System.out::println);
    
  • toArray
    将流转化成数组

    //流转化字符串数组
    String[] s = Stream.of("a","b").toArray(String[]::new);
    //流转化对象数组
    Person p1 = new Person("zhangsan",14);
    Person p2 = new Person("lisi",18);
    Person[] p = Stream.of(p1,p2).toArray(Person[]::new);
    
  • reduce
    对stream类元素进行聚合求值

    List<Integer> numList = Arrays.asList(1,2,3,4,5);
    List<String> strList = Arrays.asList("a","b","c","d","e");
    numList.stream().reduce((a,b) -> a + b ).get();//15,1+2+3+4+5
    numList.stream().reduce((a,b) -> a - b ).get();//-13,1-2-3-4-5
    strList.stream().reduce((a,b) -> a + b ).get();//"abcde"
    
  • collect
    主要用于将Stream中的元素通过一定的计算过程转化为另外的表现形式,这里就要提到Collectors这个转化类。Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串。Collectors 官方Api文档

    Collectors.toList()//将stream流转化成List
    Collectors.joining()//将stream每个元素拼接形成字符串
    Collectors.joining(",")//将stream每个元素拼接形成字符串(中间用逗号隔开)
    //上面例子我们已经了解到如何转化回集合,下面例子是拼接非空字符串:
    String str = list.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(","));
    
  • min/max
    按照规则取最大值或最小值

    //下面例子找出年龄最大的人
    Person p1 = new Person("zhangsan",11);
    Person p2 = new Person("wangwu",18);
    Person p3 = new Person("lisi",11);
    Person p = Stream.of(p1,p2,p3).max(Comparator.comparing(Person::getAge)).get();
    System.out.println(p);//输出结果:Person(name=wangwu, age=18)(如果找最少是zhangsan)
    
  • count
    返回元素的个数

    Person p1 = new Person("zhangsan",11);
    Person p2 = new Person("wangwu",18);
    Person p3 = new Person("lisi",11);
    //找到上面三个人中年龄11岁的有几个
    int a = (int)Stream.of(p1,p2,p3).filter(i->i.getAge()==11).count();
    System.out.println(a);//输出结果:2
    
  • anyMatch/allMatch/noneMatch
    对stream元素作判断时用,传入一个Predicate参数,返回一个boolean类型的判断结果。
    anyMatch:当一个或多个元素满足条件返回true。
    allMatch:当所有元素满足条件返回true。
    noneMatch:当一个或多个元素满足条件返回true。

    Person p1 = new Person("zhangsan",11);
    Person p2 = new Person("wangwu",18);
    Person p3 = new Person("lisi",11);
    boolean a = Stream.of(p1,p2,p3).allMatch(i->i.getAge()>15);//false,元素全大于15
    boolean b = Stream.of(p1,p2,p3).anyMatch(i->i.getAge()>15);//true,有元素大于15
    boolean c = Stream.of(p1,p2,p3).noneMatch(i->i.getAge()>15);//false,没有元素大于15
    
  • findFirst/findAny
    findFirst找到steam的第一个元素,findAny找到任意一个。在串行流中,两个返回的都是第一个元素,而在并行流中,findAny返回的元素就不固定了

    List<String> list = Arrays.asList("a", "b", "c", "d", "e");
    String a =list.stream().findFirst().get();//"a"
    String b =list.stream().findAny().get();//"a"
    String c =list.parallelStream().findFirst().get();//"a"
    String d =list.parallelStream().findAny().get();//"c"(随机)
    
  • (static)builder
    创建一个具有生命周期的流构建器,构建一个有序的Stream。
    有三个方法:
    void accept​(T t)
    default Stream.Builder add​(T t)
    Stream build()
    官方Api文档

  • (static)empty/of/ofNullable
    单个参数构造方法ofNullable/of,ofNullable可为null,of不能null,empty为空stream

    //新建
    Stream.ofNullable("a","b","c","","d");
    Stream.of("a","b","c");
    Stream.empty();
    
  • (static)iterate/generate
    通过函数的形式生成流

    //注意下面生成的是无限流,所以用limit控制元素个数
    Stream.iterate(0, i -> ++i).limit(5);//0,1,2,3,4 0是初始值
    Stream.generate( () -> "a").limit(5);//a,a,a,a,a
    
  • (static)concat
    合并多个stream

    Stream.concat(Stream.of("a","b"), Stream.of("b","c"))//a,b,b,c
    
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值