Java 8 Stream API 详解

打印 上一主题 下一主题

主题 971|帖子 971|积分 2913

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目次
引言
一、Stream 简介
1.1 什么是 Stream?
1.2 Stream 与聚集的区别
1.3 Stream 的操纵分类
二、Stream 的创建
2.1 从聚集创建
2.2 从数组创建
2.3 使用 Stream.of 创建         
2.4 使用 Stream.generate 或 Stream.iterate 创建
三、Stream 的常用操纵
3.1 中间操纵
3.1.1 filter:过滤
3.1.2 map:映射
3.1.3 sorted:排序
3.1.4 distinct:去重
3.1.5 limit 和 skip:限制和跳过
3.2 终端操纵
3.2.1 forEach:遍历
3.2.2 collect:收集
3.2.3 reduce:归约
3.2.4 count:计数
3.2.5 anyMatch、allMatch、noneMatch:匹配
四、并行流
五、总结

引言

Java 8 引入了 Stream API,它提供了一种高效且声明式的方式来处理聚集数据。Stream API 的核心思想是将数据的操纵分为中间操纵终端操纵,并通过流水线(Pipeline)的方式进行处理。Stream API 不仅使代码更加简洁易读,还能充分利用多核处理器的优势,提拔数据处理性能。

一、Stream 简介

1.1 什么是 Stream?

Stream 是 Java 8 中处理聚集数据的抽象工具。它并不是数据结构,而是一种对数据源(如聚集、数组等)进行高效聚合操纵的工具。Stream 的特点包罗:


  • 声明式编程:通过链式调用方法描述数据处理逻辑。
  • 惰性求值:中间操纵不会立刻实行,只有在终端操纵触发时才会实行。
  • 并行处理:可以轻松实现并行操纵,充分利用多核 CPU。
1.2 Stream 与聚集的区别



  • 聚集:存储和操纵数据的容器,关注数据的存储和访问。
  • Stream:对数据进行计算和处理的工具,关注数据的计算和转换。
1.3 Stream 的操纵分类

Stream 的操纵分为两类:

  • 中间操纵(Intermediate Operations):返回一个新的 Stream,可以链式调用。例如 filter、map、sorted 等。
  • 终端操纵(Terminal Operations):触发 Stream 的实行并返回效果。例如 forEach、collect、reduce 等。

二、Stream 的创建

Stream 可以从多种数据源创建,例如聚集、数组、I/O 资源等。
2.1 从聚集创建

  1. List<String> list = Arrays.asList("Java", "Python", "C++");
  2. Stream<String> stream = list.stream(); // 创建顺序流
  3. Stream<String> parallelStream = list.parallelStream(); // 创建并行流
复制代码
2.2 从数组创建

  1. String[] array = {"Java", "Python", "C++"};
  2. Stream<String> stream = Arrays.stream(array);
复制代码
2.3 使用 Stream.of 创建         

  1. Stream<String> stream = Stream.of("Java", "Python", "C++");
复制代码
2.4 使用 Stream.generate 或 Stream.iterate 创建

  1. // 生成无限流
  2. Stream<String> infiniteStream = Stream.generate(() -> "Hello");
  3. // 生成有限流
  4. Stream<Integer> finiteStream = Stream.iterate(0, n -> n + 1).limit(10);
复制代码

三、Stream 的常用操纵


3.1 中间操纵

3.1.1 filter:过滤

根据条件过滤元素。
  1. List<String> languages = Arrays.asList("Java", "Python", "C++", "JavaScript");
  2. List<String> result = languages.stream()
  3.                                .filter(s -> s.startsWith("J"))
  4.                                .collect(Collectors.toList());
  5. System.out.println(result); // 输出 [Java, JavaScript]
复制代码
3.1.2 map:映射

将元素转换为另一种形式。
  1. List<String> languages = Arrays.asList("Java", "Python", "C++");
  2. List<Integer> lengths = languages.stream()
  3.                                  .map(String::length)
  4.                                  .collect(Collectors.toList());
  5. System.out.println(lengths); // 输出 [4, 6, 3]
复制代码
3.1.3 sorted:排序

对元素进行排序。
  1. List<String> languages = Arrays.asList("Java", "Python", "C++");
  2. List<String> sortedLanguages = languages.stream()
  3.                                        .sorted()
  4.                                        .collect(Collectors.toList());
  5. System.out.println(sortedLanguages); // 输出 [C++, Java, Python]
复制代码
3.1.4 distinct:去重

去除重复元素。
  1. List<String> languages = Arrays.asList("Java", "Python", "Java", "C++");
  2. List<String> uniqueLanguages = languages.stream()
  3.                                        .distinct()
  4.                                        .collect(Collectors.toList());
  5. System.out.println(uniqueLanguages); // 输出 [Java, Python, C++]
复制代码
3.1.5 limit 和 skip:限制和跳过



  • limit(n):保存前 n 个元素。
  • skip(n):跳过前 n 个元素。
  1. List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
  2. List<Integer> result = numbers.stream()
  3.                               .limit(3)
  4.                               .skip(1)
  5.                               .collect(Collectors.toList());
  6. System.out.println(result); // 输出 [2, 3]
复制代码

3.2 终端操纵

3.2.1 forEach:遍历

对每个元素实行操纵。
  1. List<String> languages = Arrays.asList("Java", "Python", "C++");
  2. languages.stream().forEach(System.out::println);
复制代码
3.2.2 collect:收集

将 Stream 转换为聚集或其他数据结构。
  1. List<String> languages = Arrays.asList("Java", "Python", "C++");
  2. Set<String> languageSet = languages.stream()
  3.                                    .collect(Collectors.toSet());
  4. System.out.println(languageSet); // 输出 [Java, Python, C++]
复制代码
3.2.3 reduce:归约

将 Stream 中的元素组合起来,得到一个值。
  1. List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
  2. int sum = numbers.stream()
  3.                  .reduce(0, Integer::sum);
  4. System.out.println(sum); // 输出 15
复制代码
3.2.4 count:计数

返回 Stream 中元素的个数。
  1. List<String> languages = Arrays.asList("Java", "Python", "C++");
  2. long count = languages.stream().count();
  3. System.out.println(count); // 输出 3
复制代码
3.2.5 anyMatch、allMatch、noneMatch:匹配



  • anyMatch:恣意一个元素满意条件。
  • allMatch:所有元素都满意条件。
  • noneMatch:没有元素满意条件。
  1. List<String> languages = Arrays.asList("Java", "Python", "C++");
  2. boolean anyMatch = languages.stream().anyMatch(s -> s.startsWith("J"));
  3. boolean allMatch = languages.stream().allMatch(s -> s.length() > 3);
  4. boolean noneMatch = languages.stream().noneMatch(s -> s.isEmpty());
  5. System.out.println(anyMatch); // 输出 true
  6. System.out.println(allMatch); // 输出 false
  7. System.out.println(noneMatch); // 输出 true
复制代码

四、并行流

Stream API 支持并行处理,只需将 stream() 更换为 parallelStream() 即可。
  1. List<String> languages = Arrays.asList("Java", "Python", "C++");
  2. long count = languages.parallelStream()
  3.                      .filter(s -> s.startsWith("J"))
  4.                      .count();
  5. System.out.println(count); // 输出 1
复制代码

五、案例

User实体类
  1. public class User {
  2.     private int id;
  3.     private String userName;
  4.     private int age;
  5.     //get、set、有参/无参构造器、toString
  6. }
复制代码
Stream算法题
  1. import java.util.Arrays;
  2. import java.util.List;
  3. /*
  4. * 题目:请按照给出数据,找出同时满足以下条件的用户
  5. *       也即以下条件:
  6. *          1、全部满足偶数ID
  7. *          2、年龄大于24
  8. *          3、用户名转为大写
  9. *          4、用户名字母倒排序
  10. *          5、只输出一个用户名字 limit
  11. **/
  12. public class StreamDemo {
  13.     public static void main(String[] args) {
  14.         User u1 = new User(11, "a", 23);
  15.         User u2 = new User(12, "b", 24);
  16.         User u3 = new User(13, "c", 22);
  17.         User u4 = new User(14, "d", 28);
  18.         User u5 = new User(16, "e", 26);
  19.         List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
  20.         /*
  21.          * 1. 首先我们需要将 list 转化为stream流
  22.          * 2. 然后将用户过滤出来,这里用到一个函数式接口Predicate<? super T>,我们可
  23. 以使用lambda表达式简化
  24.          * 3. 这里面传递的参数,就是Stream流的泛型类型,也就是User,所以,这里可以直接
  25. 返回用户id为偶数的用户信息;
  26.          * 4. 通过forEach进行遍历,直接简化输出 System.out::println ,等价于
  27. System.out.println(u);
  28.          **/
  29.         //list.stream().filter(u -> {return
  30. //u.getId()%2==0;}).forEach(System.out::println);
  31.         //list.stream().filter(u -> {return u.getId()%2==0;})
  32.             //.filter(u -> {return
  33. //u.getAge()>24;}).forEach(System.out::println);
  34.         //sorted()  自然排序,正排序 D->E
  35.         list.stream()
  36.                 .filter(u -> {return u.getId()%2==0;})
  37.                 .filter(u -> {return u.getAge()>24;})
  38.                 .map(u -> {return u.getUserName().toUpperCase();})
  39.               //.sorted() //默认正排序  自己用 compareTo 比较
  40.                 .sorted((o1,o2)->{return o2.compareTo(o1);})
  41.                 .limit(1)
  42.                 .forEach(System.out::println);
  43.         /*
  44.             map解释
  45.             List<Integer> list2 = Arrays.asList(1,2,3);
  46.             list2 = list2.stream().map(x -> {return
  47.             x*2;}).collect(Collectors.toList());
  48.              for (Integer element : list2) {
  49.                  System.out.println(element);
  50.              }
  51.          */
  52.      }
  53. }
复制代码


六、总结

Stream API 是 Java 8 中非常强大的工具,它通过声明式的方式简化了聚集数据的处理。通过掌握 Stream 的创建、中间操纵和终端操纵,你可以写出更简洁、高效的代码。以下是本文的核心要点:

  • Stream 的创建:可以从聚集、数组、I/O 资源等创建 Stream。
  • 中间操纵:如 filter、map、sorted 等,用于对数据进行处理和转换。
  • 终端操纵:如 forEach、collect、reduce 等,用于触发计算并返回效果。
  • 并行流:通过 parallelStream() 实现并行处理,提拔性能。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

冬雨财经

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表