2022.11.11 Stream流

3. Stream流

3.1 概述

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

 

3.2 案例数据准备

1      <dependencies>
2          <dependency>
3              <groupId>org.projectlombok</groupId>
4              <artifactId>lombok</artifactId>
5              <version>1.18.16</version>
6          </dependency>
7      </dependencies>
复制代码
 1  package com.xing.demo01;
 2  3  import lombok.AllArgsConstructor;
 4  import lombok.Data;
 5  import lombok.EqualsAndHashCode;
 6  import lombok.NoArgsConstructor;
 7  8  import java.util.List;
 9 10  @Data
11  @NoArgsConstructor
12  @AllArgsConstructor
13  @EqualsAndHashCode//重写equals() 和hashCode()
14  public class Author {
15      //id
16      private Long id;
17      //姓名
18      private String name;
19      //年龄
20      private Integer age;
21      //简介
22      private String intro;
23      //作品
24      private List<Book> books;
25  }
复制代码
复制代码
 1  package com.xing.demo01;
 2  3  import lombok.AllArgsConstructor;
 4  import lombok.Data;
 5  import lombok.EqualsAndHashCode;
 6  import lombok.NoArgsConstructor;
 7  8  @Data
 9  @AllArgsConstructor
10  @NoArgsConstructor
11  @EqualsAndHashCode//用于后期的去重使用
12  public class Book {
13      //id
14      private Long id;
15      //书名
16      private String name;
17 18      //分类   可能一本属于两个类别
19      private String category;
20 21      //评分
22      private Integer score;
23 24      //简介
25      private String intro;
26 27  }
复制代码
复制代码
 1  package com.xing.demo01;
 2  3  import java.util.ArrayList;
 4  import java.util.Arrays;
 5  import java.util.List;
 6  7  /**
 8   * @program: TestTime
 9   * @Date: 2022/08/24
10   * @author: 16159
11   * @description:
12   * @Modified By:
13   **/
14  public class Test {
15      public static void main(String[] args) {
16          List<Author> authors = getAuthors();
17          
18      }
19      private static List<Author> getAuthors() {
20          //数据初始化
21          Author author = new Author(1L,"蒙多",33,"一个从菜刀中明悟哲理的祖安人",null);
22          Author author2 = new Author(2L,"亚拉索",15,"狂风也追逐不上他的思考速度",null);
23          Author author3 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
24          Author author4 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
25 26          //书籍列表
27          List<Book> books1 = new ArrayList<>();
28          List<Book> books2 = new ArrayList<>();
29          List<Book> books3 = new ArrayList<>();
30 31          books1.add(new Book(1L,"刀的两侧是光明与黑暗","哲学,爱情",88,"用一把刀划分了爱恨"));
32          books1.add(new Book(2L,"一个人不能死在同一把刀下","个人成长,爱情",99,"讲述如何从失败中明悟真理"));
33 34          books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));
35          books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));
36          books2.add(new Book(4L,"吹或不吹","爱情,个人传记",56,"一个哲学家的恋爱观注定很难把他所在的时代理解"));
37 38          books3.add(new Book(5L,"你的剑就是我的剑","爱情",56,"无法想象一个武者能对他的伴侣这么的宽容"));
39          books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
40          books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
41 42          author.setBooks(books1);
43          author2.setBooks(books2);
44          author3.setBooks(books3);
45          author4.setBooks(books3);
46 47          List<Author> authorList = new ArrayList<>(Arrays.asList(author,author2,author3,author4));
48          return authorList;
49      }
50  }
复制代码

3.3 快速入门

3.3.1 需求

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

3.3.2 实现

复制代码
 1  //打印所有年龄小于18的作家的名字,并且要注意去重
 2  List<Author> authors = getAuthors();
 3  authors.
 4      stream()//把集合转换成流
 5      .distinct()//先去除重复的作家
 6      //.filter(new Predicate<Author>(){
 7      //    @Override
 8      //    public boolean test(Author author){
 9      //        return author.getAge()<18;
10      //    }
11      //}).//筛选年龄小于18的
12      .filter(author -> author.getAge()<18)//筛选年龄小于18的
13      .forEach(author -> System.out.println(author.getName()));//遍历打印名字
复制代码

 

3.4 常用操作

一个流的操作流程必须经过三步

3.4.1 创建流

单列集合: 集合对象.stream()

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

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

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

双列集合:转换成单列集合后再创建

1  Map<String,Integer> map = new HashMap<>();
2  map.put("蜡笔小新",19);
3  map.put("黑子",17);
4  map.put("日向翔阳",16);
5 6  Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();

3.4.2 中间操作

filter

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

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

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

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

例如:打印所有作家的姓名

复制代码
 1          List<Author> authors = getAuthors();
 2  3          authors
 4                  .stream()
 5                  // 范型1:流当中元素的类型(基本不能改)  范型2:期望转换成的类型
 6                  // .map(new Function<Author, String>() {
 7                  //     @Override
 8                  //     //参数为范型1   返回值为范型2
 9                  //     public String apply(Author author) {
10                  //         return author.getName();
11                  //     }
12                  // })   经过操作流当中的元素为姓名
13                  .map(author -> author.getName())
14                  .forEach(name->System.out.println(name));
15  //        打印所有作家的年龄+10
16          List<Author> authors = getAuthors();
17          authors.stream()
18                  .map(author -> author.getAge())
19                  .map(age->age+10)
20                  .forEach(age-> System.out.println(age));
复制代码
distinct

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

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

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

 

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

sorted

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

例如:对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。

 

 

sorted()不带参数,会把流中的元素转换成Comparable,但是Author与Comparable无关,会报错

复制代码
 1  package com.xing.demo01;
 2  3  import java.util.ArrayList;
 4  import java.util.Arrays;
 5  import java.util.List;
 6  import java.util.function.Consumer;
 7  import java.util.function.Function;
 8  9  /**
10   * @program: TestTime
11   * @Date: 2022/08/24
12   * @author: 16159
13   * @description:
14   * @Modified By:
15   **/
16  public class Test {
17      public static void main(String[] args) {
18          List<Author> authors = getAuthors();
19          authors.stream()
20                  .distinct()
21                  .sorted()
22                  .forEach(author -> System.out.println(author.getAge()));
23      }
24      private static List<Author> getAuthors() {
25          //数据初始化
26          Author author = new Author(1L,"蒙多",33,"一个从菜刀中明悟哲理的祖安人",null);
27          Author author2 = new Author(2L,"亚拉索",15,"狂风也追逐不上他的思考速度",null);
28          Author author3 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
29          Author author4 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
30 31          //书籍列表
32          List<Book> books1 = new ArrayList<>();
33          List<Book> books2 = new ArrayList<>();
34          List<Book> books3 = new ArrayList<>();
35 36          books1.add(new Book(1L,"刀的两侧是光明与黑暗","哲学,爱情",88,"用一把刀划分了爱恨"));
37          books1.add(new Book(2L,"一个人不能死在同一把刀下","个人成长,爱情",99,"讲述如何从失败中明悟真理"));
38 39          books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));
40          books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));
41          books2.add(new Book(4L,"吹或不吹","爱情,个人传记",56,"一个哲学家的恋爱观注定很难把他所在的时代理解"));
42 43          books3.add(new Book(5L,"你的剑就是我的剑","爱情",56,"无法想象一个武者能对他的伴侣这么的宽容"));
44          books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
45          books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
46 47          author.setBooks(books1);
48          author2.setBooks(books2);
49          author3.setBooks(books3);
50          author4.setBooks(books3);
51 52          List<Author> authorList = new ArrayList<>(Arrays.asList(author,author2,author3,author4));
53          return authorList;
54      }
55 56 57  }
复制代码

解决方法:Author类实现Comparable接口

复制代码
 1  package com.xing.demo01;
 2  3  import lombok.AllArgsConstructor;
 4  import lombok.Data;
 5  import lombok.EqualsAndHashCode;
 6  import lombok.NoArgsConstructor;
 7  8  import java.util.List;
 9 10  @Data
11  @NoArgsConstructor
12  @AllArgsConstructor
13  @EqualsAndHashCode//用于后期的去重使用
14  public class Author implements Comparable<Author>{
15      //id
16      private Long id;
17      //姓名
18      private String name;
19      //年龄
20      private Integer age;
21      //简介
22      private String intro;
23      //作品
24      private List<Book> books;
25 26      //在这里面定义比较规则   当前的与传入的相比较年龄大小  
27      @Override
28      public int compareTo(Author o) {
29          return this.getAge()-o.getAge();
30      }
31  }
复制代码

 

注意:如果调用空参的sorted()方法,需要流中的元素是实现了Comparable。

带参数不需要实现接口

1          List<Author> authors = getAuthors();
2  //        对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。
3          authors.stream()
4                  .distinct()
5                  .sorted((o1, o2) -> o2.getAge()-o1.getAge())
6                  .forEach(author -> System.out.println(author.getAge()))
limit

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

例如:对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素,然后打印其中年龄最大的两个作家的姓名。

1          List<Author> authors = getAuthors();
2          authors.stream()
3                  .distinct()
4                  .sorted()
5                  .limit(2)//只留两条
6                  .forEach(author -> System.out.println(author.getName()));

 

skip

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

例如:打印除了年龄最大的作家外的其他作家,要求不能有重复元素,并且按照年龄降序排序。

1  //        打印除了年龄最大的作家外的其他作家,要求不能有重复元素,并且按照年龄降序排序。
2          List<Author> authors = getAuthors();
3          authors.stream()
4                  .distinct()
5                  .sorted()
6                  .skip(1)//跳过第一条
7                  .forEach(author -> System.out.println(author.getName()));

 

flatMap

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

例一:打印所有书籍的名字。要求对重复的元素进行去重。

复制代码
 1  package com.xing.demo01;
 2  3  import java.util.ArrayList;
 4  import java.util.Arrays;
 5  import java.util.List;
 6  import java.util.function.Consumer;
 7  import java.util.function.Function;
 8  import java.util.stream.Stream;
 9 10  /**
11   * @program: TestTime
12   * @Date: 2022/08/24
13   * @author: 16159
14   * @description:
15   * @Modified By:
16   **/
17  public class Test {
18      public static void main(String[] args) {
19          List<Author> authors = getAuthors();
20 21          authors.stream()
22                  .flatMap(new Function<Author, Stream<Book>>() {
23                      @Override
24                      public Stream<Book> apply(Author author) {
25                          //author.getBooks()得到List<Book>   需要再转换为流,其类型为Book类型  Stream范型改为Book
26                          return author.getBooks().stream();
27                      }
28                  })
29                  .distinct()
30                  .forEach(new Consumer<Book>() {
31                      @Override
32                      public void accept(Book book) {
33                          System.out.println(book.getName());
34                      }
35                  });
36 37      }
38      private static List<Author> getAuthors() {
39          //数据初始化
40          Author author = new Author(1L,"蒙多",33,"一个从菜刀中明悟哲理的祖安人",null);
41          Author author2 = new Author(2L,"亚拉索",15,"狂风也追逐不上他的思考速度",null);
42          Author author3 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
43          Author author4 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
44 45          //书籍列表
46          List<Book> books1 = new ArrayList<>();
47          List<Book> books2 = new ArrayList<>();
48          List<Book> books3 = new ArrayList<>();
49 50          books1.add(new Book(1L,"刀的两侧是光明与黑暗","哲学,爱情",88,"用一把刀划分了爱恨"));
51          books1.add(new Book(2L,"一个人不能死在同一把刀下","个人成长,爱情",99,"讲述如何从失败中明悟真理"));
52 53          books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));
54          books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));
55          books2.add(new Book(4L,"吹或不吹","爱情,个人传记",56,"一个哲学家的恋爱观注定很难把他所在的时代理解"));
56 57          books3.add(new Book(5L,"你的剑就是我的剑","爱情",56,"无法想象一个武者能对他的伴侣这么的宽容"));
58          books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
59          books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
60 61          author.setBooks(books1);
62          author2.setBooks(books2);
63          author3.setBooks(books3);
64          author4.setBooks(books3);
65 66          List<Author> authorList = new ArrayList<>(Arrays.asList(author,author2,author3,author4));
67          return authorList;
68      }
69 70 71  }
复制代码

简写

1  //        打印所有书籍的名字。要求对重复的元素进行去重。
2          List<Author> authors = getAuthors();
3 4          authors.stream()
5                  .flatMap(author -> author.getBooks().stream())
6                  .distinct()
7                  .forEach(book -> System.out.println(book.getName()));

 

例二:

打印现有数据的所有分类。要求对分类进行去重。不能出现这种格式:哲学,爱情

复制代码
 1  package com.xing.demo01;
 2  3  import java.util.ArrayList;
 4  import java.util.Arrays;
 5  import java.util.List;
 6  import java.util.function.Consumer;
 7  import java.util.function.Function;
 8  import java.util.stream.Stream;
 9 10  /**
11   * @program: TestTime
12   * @Date: 2022/08/24
13   * @author: 16159
14   * @description:
15   * @Modified By:
16   **/
17  public class Test {
18      public static void main(String[] args) {
19          List<Author> authors = getAuthors();
20 21          authors.stream()
22                  .flatMap(author -> author.getBooks().stream())
23                  .distinct() //对书籍进行去重
24                  //              将数组转换为流  split(",")以,为分隔符  String s = book.getCategory();//哲学,爱情   String[] split = s.split(",");//["哲学","爱情"]
25                  .flatMap(book -> Arrays.stream(book.getCategory().split(",")))
26                  .distinct()//对分类的字符串进行去重
27                  .forEach(category-> System.out.println(category));
28 29      }
30      private static List<Author> getAuthors() {
31          //数据初始化
32          Author author = new Author(1L,"蒙多",33,"一个从菜刀中明悟哲理的祖安人",null);
33          Author author2 = new Author(2L,"亚拉索",15,"狂风也追逐不上他的思考速度",null);
34          Author author3 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
35          Author author4 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
36 37          //书籍列表
38          List<Book> books1 = new ArrayList<>();
39          List<Book> books2 = new ArrayList<>();
40          List<Book> books3 = new ArrayList<>();
41 42          books1.add(new Book(1L,"刀的两侧是光明与黑暗","哲学,爱情",88,"用一把刀划分了爱恨"));
43          books1.add(new Book(2L,"一个人不能死在同一把刀下","个人成长,爱情",99,"讲述如何从失败中明悟真理"));
44 45          books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));
46          books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));
47          books2.add(new Book(4L,"吹或不吹","爱情,个人传记",56,"一个哲学家的恋爱观注定很难把他所在的时代理解"));
48 49          books3.add(new Book(5L,"你的剑就是我的剑","爱情",56,"无法想象一个武者能对他的伴侣这么的宽容"));
50          books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
51          books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
52 53          author.setBooks(books1);
54          author2.setBooks(books2);
55          author3.setBooks(books3);
56          author4.setBooks(books3);
57 58          List<Author> authorList = new ArrayList<>(Arrays.asList(author,author2,author3,author4));
59          return authorList;
60      }
61 62 63  }
复制代码

3.4.3 终结操作

forEach

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

例子:输出所有作家的名字

1  //        输出所有作家的名字
2          List<Author> authors = getAuthors();
3 4          authors.stream()
5                  .map(author -> author.getName())
6                  .distinct()
7                  .forEach(name-> System.out.println(name));
count

可以用来获取当前流中元素的个数。

例子:打印这些作家的所出书籍的数目,注意删除重复元素。

1  //        打印这些作家的所出书籍的数目,注意删除重复元素。
2          List<Author> authors = getAuthors();
3 4          long count = authors.stream()
5                  .flatMap(author -> author.getBooks().stream())
6                  .distinct()
7                  .count();//不需要参数,但是有返回值
8          System.out.println(count);
max&min

可以用来或者流中的最值。

例子:分别获取这些作家的所出书籍的最高分和最低分并打印。

复制代码
 1  //        分别获取这些作家的所出书籍的最高分和最低分并打印。
 2          //Stream<Author>  -> Stream<Book> ->Stream<Integer>  ->求值
 3  4          List<Author> authors = getAuthors();
 5          Optional<Integer> max = authors.stream()
 6                  //Stream<Author>  -> Stream<Book>
 7                  .flatMap(author -> author.getBooks().stream())
 8                  //Stream<Book> ->Stream<Integer>
 9                  .map(book -> book.getScore())
10                  /*max有返回值 Optional类型
11                  .max(new Comparator<Integer>() {
12                      @Override
13                      public int compare(Integer score1, Integer score2) {//比较o1与o2的值
14                          return score1-score2;
15                      }
16                  });*/
17                  .max((score1, score2) -> score1 - score2);
18          System.out.println(max.get());//打印最大值 100
19 20 21          Optional<Integer> min = authors.stream()
22                  .flatMap(author -> author.getBooks().stream())
23                  .map(book -> book.getScore())
24                  .min((score1, score2) -> score1 - score2);
25          System.out.println(min.get());
复制代码

 

collect

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

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

1  //获取一个存放所有作者名字的List集合。
2  List<Author> authors = getAuthors();
3 4  List<String> nameList = authors.stream()
5      .map(author -> author.getName())
6      .collect(Collectors.toList());//有返回值  工具类Collectors的toList()      返回一个list
7  System.out.println(nameList);

获取一个所有书名的Set集合。

1  //获取一个所有书名的Set集合。
2  List<Author> authors = getAuthors();
3  Set<Book> books = authors.stream()
4      .flatMap(author -> author.getBooks().stream())
5      .collect(Collectors.toSet());//有返回值  工具类Collectors的toSet()      返回一个set
6 7  System.out.println(books);

获取一个Map集合,map的key为作者名,value为List<Book>

复制代码
 1  //获取一个Map集合,map的key为作者名,value为List<Book>
 2          List<Author> authors = getAuthors();
 3  4          Map<String, List<Book>> map = authors.stream()
 5                  .distinct()               //中间操作的map
 6                  .collect(Collectors.toMap(new Function<Author, String>() {
 7                      @Override
 8                      public String apply(Author author) {
 9                          return author.getName();
10                      }
11                  }, new Function<Author, List<Book>>() {
12                      @Override
13                      public List<Book> apply(Author author) {
14                          return author.getBooks();
15                      }
16                  }));
17 18          System.out.println(map);
复制代码

简写

1  //获取一个Map集合,map的key为作者名,value为List<Book>
2  List<Author> authors = getAuthors();
3 4  Map<String, List<Book>> map = authors.stream()
5      .distinct()               //中间操作的map
6      .collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));
7 8  System.out.println(map);
查找与匹配
anyMatch

可以用来判断是否有任意符合匹配条件的元素,结果为boolean类型。

例子:判断是否有年龄在29以上的作家

1  //        判断是否有年龄在29以上的作家   有就返回true
2          List<Author> authors = getAuthors();
3          boolean flag = authors.stream()
4                  .anyMatch(author -> author.getAge() > 29);
5          System.out.println(flag);
allMatch

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

例子:判断是否所有的作家都是成年人

1  //        判断是否所有的作家都是成年人   全部符合才返回true
2          List<Author> authors = getAuthors();
3          boolean flag = authors.stream()
4                  .allMatch(author -> author.getAge() >= 18);
5          System.out.println(flag);
noneMatch

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

例子:判断作家是否都没有超过100岁的。

1  //        判断作家是否都没有超过100岁的。
2          List<Author> authors = getAuthors();
3 4          boolean b = authors.stream()
5                  .noneMatch(author -> author.getAge() > 100);
6 7          System.out.println(b);
findAny

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

例子:获取任意一个年龄大于18的作家,如果存在就输出他的名字

1  //        获取任意一个年龄大于18的作家,如果存在就输出他的名字
2          List<Author> authors = getAuthors();
3          Optional<Author> optionalAuthor = authors.stream()
4                  .filter(author -> author.getAge()>18)//筛选完有可能没有元素
5                  .findAny();//返回Optional
6 7          //ifPresent 如果存在元素就执行里面的操作  避免空指针异常
8          optionalAuthor.ifPresent(author -> System.out.println(author.getName()));
findFirst

获取流中的第一个元素。

例子:获取一个年龄最小的作家,并输出他的姓名。

1  //        获取一个年龄最小的作家,并输出他的姓名。
2          List<Author> authors = getAuthors();
3          Optional<Author> first = authors.stream()
4                  .sorted((o1, o2) -> o1.getAge() - o2.getAge())
5                  .findFirst();//返回Optional
6 7          first.ifPresent(author -> System.out.println(author.getName()));
reduce归并

对流中的数据按照你指定的计算方式计算出一个结果。(缩减操作)

reduce的作用是把stream中的元素给组合起来,我们可以传入一个初始值,它会按照我们的计算方式依次拿流中的元素和初始值进行计算,计算结果再和后面的元素计算。

reduce两个参数的重载形式内部的计算方式如下

1  //给result变量一个初始值  T为流中元素的类型
2  T result = identity;    
3  for (T element : this stream)
4      result = accumulator.apply(result, element)
5  return result;

其中identity就是我们可以通过方法参数传入的初始值,accumulator的apply具体进行什么计算也是我们通过方法参数来确定的。

例子:使用reduce求所有作者年龄的和

复制代码
 1  Integer sum = authors.stream()
 2      .distinct()
 3      .map(author -> author.getAge())
 4      //    初始值
 5      .reduce(0, new BinaryOperator<Integer>() {
 6          @Override
 7          //                   定义的初始值0      本次遍历到的值
 8          public Integer apply(Integer result, Integer element) {
 9              // 内部会把得到的结果在赋值给result
10              return result + element;
11          }
12      });
复制代码

简写

1  //        使用reduce求所有作者年龄的和
2          List<Author> authors = getAuthors();
3          Integer sum = authors.stream()
4                  .distinct()
5                  .map(author -> author.getAge())
6                  .reduce(0, (result, element) -> result + element);
7          System.out.println(sum);

使用reduce求所有作者中年龄的最大值

1  //        使用reduce求所有作者中年龄的最大值
2          List<Author> authors = getAuthors();
3          Integer max = authors.stream()
4                  .map(author -> author.getAge())
5                  //初始值设置为Integer最小值
6                  .reduce(Integer.MIN_VALUE, (result, element) -> result < element ? element : result);
7 8          System.out.println(max);

使用reduce求所有作者中年龄的最小值

1  //        使用reduce求所有作者中年龄的最小值
2          List<Author> authors = getAuthors();
3          Integer min = authors.stream()
4                  .map(author -> author.getAge())
5                  .reduce(Integer.MAX_VALUE, (result, element) -> result > element ? element : result);
6          System.out.println(min);

reduce一个参数的重载形式内部的计算

复制代码
 1  boolean foundAny = false;
 2  //初始值
 3  T result = null;
 4  //遍历流中的元素
 5  for (T element : this stream) {
 6      //把流中的第一个元素的值赋值给初始值
 7      if (!foundAny) {
 8          foundAny = true;
 9          result = element;
10      }
11      //除了第一次循环,后面都是执行else语句
12      else
13          result = accumulator.apply(result, element);
14  }
15  return foundAny ? Optional.of(result) : Optional.empty();
复制代码

如果用一个参数的重载方法去求最小值代码如下:

1          //        使用reduce求所有作者中年龄的最小值
2          List<Author> authors = getAuthors();
3          Optional<Integer> minOptional = authors.stream()
4                  .map(author -> author.getAge())
5                  .reduce((result, element) -> result > element ? element : result);
6          minOptional.ifPresent(age-> System.out.println(age));

3.5 注意事项

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

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

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

posted @   暴躁C语言  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示