函数式编程part3-Stream流

3.1 概述

  Java8的Stream使用的是函数式编程模式,

  如同它的名字一样,它可以被用来对集合或数组进行链状流式的操作。可以更方便的让我们对集合或数组操作。

 

3.3 快速入门

3.3.1 需求

我们可以调用getAuthors方法获取到作家的集合。现在需要打印所有年龄小于18的作家的名字,并且要注意去重。

3.3.2 实现

复制代码
        //打印所有年龄小于18的作家的名字,并且要注意去重
        List<Author> authors = getAuthors();
        authors.
                stream()//把集合转换成流
                .distinct()//先去除重复的作家
                .filter(author -> author.getAge()<18)//筛选年龄小于18的
                .forEach(author -> System.out.println(author.getName()));//遍历打印名字
复制代码

 

3.4 常用操作

3.4.1 创建流

单列集合: 集合对象.stream(),父接口为collection

            List<Author> authors = getAuthors();
            Stream<Author> stream = authors.stream();                

 

数组:Arrays.stream(数组)或者使用Stream.of来创建

     Integer[] arr = {1,2,3,4,5};
        Stream<Integer> stream = Arrays.stream(arr);
        Stream<Integer> stream2 = Stream.of(arr);

双列集合:使用entrySet()方法转换成单列集合后再创建,父接口是Map,使用

复制代码
 Map<String,Integer> map = new HashMap<>();
        map.put("蜡笔小新",19);
        map.put("黑子",17);
        map.put("日向翔阳",16);

        Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();
复制代码

3.4.2 中间操作

filter()

  可以对流中的元素进行条件过滤,符合过滤条件的才能继续留在流中。

  打印所有姓名长度大于1的作家的姓名

List<Author> authors = getAuthors();
        authors.stream()
                .filter(author -> author.getName().length()>1)
                .forEach(author -> System.out.println(author.getName()));

map()

  可以把对流中的元素进行计算或转换。返回集合

  打印所有作家的姓名

复制代码
List<Author> authors = getAuthors();

        authors
                .stream()
                .map(author -> author.getName())
                .forEach(name->System.out.println(name));
复制代码

distinct()

  可以去除流中的重复元素。

  注意:distinct方法是依赖Object的equals方法来判断是否是相同对象的。所以需要注意重写equals方法。

  打印所有作家的姓名,并且要求其中不能有重复元素。  

 List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .forEach(author -> System.out.println(author.getName()));

 

sorted()

  可以对流中的元素进行排序。

   对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。
  如果调用空参的sorted()方法,需要流中的元素是实现了Comparable接口。比如实体类要implements Comparable<实体类>
  例:对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。
  使用匿名内部类形式去调用Comparable的compare方法,最终结果经过Lambda如下
复制代码
```java
        List<Author> authors = getAuthors();
//        对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。
        authors.stream()
                .distinct()
                .sorted((o1, o2) -> o2.getAge()-o1.getAge())
                .forEach(author -> System.out.println(author.getAge()));
```
复制代码

limit()

  可以设置流的最大长度,超出的部分将被抛弃。

skip()

  跳过流中的前n个元素,返回剩下的元素

flatMap()

  map只能把一个对象转换成另一个对象来作为流中的元素。

  而flatMap可以把一个对象转换成多个对象作为流中的元素

 

3.4.3 终结操作

forEach()

  对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素进行什么具体操作。

  输出所有作家的名字

复制代码
//        输出所有作家的名字
        List<Author> authors = getAuthors();

        authors.stream()
                .map(author -> author.getName())
                .distinct()
                .forEach(name-> System.out.println(name));
复制代码

count()

   可以用来获取当前流中元素的个数。
  打印这些作家的所出书籍的数目,注意删除重复元素。
  
复制代码
        List<Author> authors = getAuthors();

        long count = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .count();
        System.out.println(count);
复制代码

max()&min()

  可以用来获取流中的最值。
    分别获取这些作家的所出书籍的最高分和最低分并打印
复制代码
        List<Author> authors = getAuthors();
        Optional<Integer> max = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .map(book -> book.getScore())
                .max((score1, score2) -> score1 - score2);

        Optional<Integer> min = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .map(book -> book.getScore())
                .min((score1, score2) -> score1 - score2);
        System.out.println(max.get());
        System.out.println(min.get());
复制代码

collect()

  把当前流转换成一个集合。

  获取一个存放所有作者名字的List集合。

   .collect(Collectors.toList());
 
  获取一个所有书名的Set集合。  
  .collect(Collectors.toSet());
 
  获取一个Map集合,map的key为作者名,value为List<Book>
  .collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));

查找与匹配

anyMatch()

  可以用来判断是否有任意符合匹配条件的元素,返回结果为boolean类型。
  判断是否有年龄在29以上的作家
boolean flag = authors.stream()
                    .anyMatch(author -> author.getAge() > 29);

allMatch()

  可以用来判断是否都符合匹配条件,结果为boolean类型。如果都符合结果为true,否则结果为false。

   判断是否所有的作家都是成年人
  
boolean flag = authors.stream()
                .allMatch(author -> author.getAge() >= 18);

noneMatch()

  可以判断流中的元素是否都不符合匹配条件。如果都不符合结果为true,否则结果为false

  判断作家是否都没有超过100岁的。
boolean b = authors.stream()
                .noneMatch(author -> author.getAge() > 100);

findAny()

  获取流中的任意一个元素。该方法没有办法保证获取的一定是流中的第一个元素。

findFirst()

  获取流中的第一个元素。

reduce归并

  对流中的数据按照你指定的计算方式计算出一个结果(缩减操作)
  reduce的作用是把Stream中的元素组合起来
  我们可以传入一个一个初始值,它会按照我们的计算方式依次拿流中的元素和在初始化值的基础上进行计算,计算后再和后面的元素计算
 
  内部计算方式
  T result = 初始化值;
  for(T element : this stream)    遍历流获取元素
    result = accumulator.apply(result,element)  调用对象的某方法,传入result和当前遍历到的元素值
  return result;
 
 ——————————例————————————
  使用reduce求所有作者年龄的和
  .reduce(0, (result, element) -> result + element);
 
  使用reduce求所有作者中年龄的最大值
  .reduce(Integer.MIN_VALUE, (result, element) -> result < element ? element : result);
 
  使用reduce求所有作者中年龄的最小值
  .reduce(Integer.MAX_VALUE, (result, element) -> result > element ? element : result);
 
  reduce(一个参数)的重载形式内部计算:
  
复制代码
 boolean foundAny = false;
     T result = null;
     for (T element : this stream) {
         if (!foundAny) {
             foundAny = true;
             result = element;
         }
         else
             result = accumulator.apply(result, element);
     }
     return foundAny ? Optional.of(result) : Optional.empty();
复制代码

 

3.5 注意事项

  • 惰性求值(如果没有终结操作,没有中间操作是不会得到执行的),我们需要终结操作

  • 流是一次性的(一旦一个流对象经过一个终结操作后。这个流就不能再被使用)

  • 不会影响原数据(我们在流中可以多数据做很多处理。但是正常情况下是不会影响原来集合中的元素的。这往往也是我们期望的)

 

 

posted @   名泽  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示