经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
Java Stream中的API你都用过了吗?
来源:cnblogs  作者:架构成长指南  时间:2023/11/22 16:45:53  对本文有异议

公众号「架构成长指南」,专注于生产实践、云原生、分布式系统、大数据技术分享。

在本教程中,您将通过大量示例来学习 Java 8 Stream API。

Java 在 Java 8 中提供了一个新的附加包,称为 java.util.stream。该包由类、接口和枚举组成,允许对元素进行函数式操作。 您可以通过在程序中导入 java.util.stream包来使用流。

Stream提供以下功能:

Stream不存储元素。它只是通过计算操作的管道传送来自数据结构、数组或 I/O 通道等源的元素。

Stream本质上是函数式的,对流执行的操作不会修改其源。例如,过滤从集合获取的 Stream 会生成一个没有过滤元素的新 Stream,而不是从源集合中删除元素。

Stream是惰性的,仅在需要时才计算代码,在流的生命周期中,流的元素仅被访问一次。

与迭代器一样,必须生成新流才能重新访问源中的相同元素。
您可以使用 Stream 来 过滤、收集、打印以及 从一种数据结构转换为其他数据结构等。

Stream API 示例

1. 创建一个空的Stream

在创建空流时,应使用 empty() 方法:

  1. Stream<String> stream = Stream.empty();
  2. stream.forEach(System.out::println);

通常情况下,在创建时会使用 empty() 方法,以避免在没有元素的流中返回 null:

  1. public Stream<String> streamOf(List<String> list) {
  2. return list == null || list.isEmpty() ? Stream.empty() : list.stream();
  3. }

2.从集合中创建流

  1. import java.io.IOException;
  2. import java.util.Arrays;
  3. import java.util.Collection;
  4. import java.util.HashSet;
  5. import java.util.List;
  6. import java.util.Set;
  7. import java.util.stream.Stream;
  8. public class StreamCreationExamples {
  9. public static void main(String[] args) throws IOException {
  10. Collection<String> collection = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
  11. Stream<String> stream2 = collection.stream();
  12. stream2.forEach(System.out::println);
  13. List<String> list = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
  14. Stream<String> stream3 = list.stream();
  15. stream3.forEach(System.out::println);
  16. Set<String> set = new HashSet<>(list);
  17. Stream<String> stream4 = set.stream();
  18. stream4.forEach(System.out::println);
  19. }
  20. }

输出

  1. JAVA
  2. J2EE
  3. Spring
  4. Hibernate
  5. JAVA
  6. J2EE
  7. Spring
  8. Hibernate
  9. JAVA
  10. Hibernate
  11. J2EE
  12. Spring

3. 从数组中创建流对象

数组可以是流的源,也可以从现有数组或数组的一部分创建数组:

  1. import java.util.Arrays;
  2. import java.util.stream.Stream;
  3. public class StreamCreationExample {
  4. public static void main(String[] args) {
  5. // 使用Arrays.stream()创建流
  6. int[] numbers = {1, 2, 3, 4, 5};
  7. Stream<Integer> stream1 = Arrays.stream(numbers);
  8. System.out.println("Using Arrays.stream():");
  9. stream1.forEach(System.out::println);
  10. // 使用Stream.of()创建流
  11. String[] names = {"Alice", "Bob", "Charlie"};
  12. Stream<String> stream2 = Stream.of(names);
  13. System.out.println("Using Stream.of():");
  14. stream2.forEach(System.out::println);
  15. // 使用Stream.builder()创建流
  16. String[] colors = {"Red", "Green", "Blue"};
  17. Stream.Builder<String> builder = Stream.builder();
  18. for (String color : colors) {
  19. builder.add(color);
  20. }
  21. Stream<String> stream3 = builder.build();
  22. System.out.println("Using Stream.builder():");
  23. stream3.forEach(System.out::println);
  24. }
  25. }

输出

  1. Using Arrays.stream():
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. Using Stream.of():
  8. Alice
  9. Bob
  10. Charlie
  11. Using Stream.builder():
  12. Red
  13. Green
  14. Blue

4. 使用Stream过滤一个集合示例

在下面的示例中,我们不使用流过滤数据,看看代码是什么样的,同时我们在给出一个使用stream过滤的示例,对比一下

不使用Stream过滤一个集合示例

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. public class FilterWithoutStreamExample {
  4. public static void main(String[] args) {
  5. List<Integer> numbers = new ArrayList<>();
  6. numbers.add(10);
  7. numbers.add(20);
  8. numbers.add(30);
  9. numbers.add(40);
  10. numbers.add(50);
  11. List<Integer> filteredNumbers = new ArrayList<>();
  12. for (Integer number : numbers) {
  13. if (number > 30) {
  14. filteredNumbers.add(number);
  15. }
  16. }
  17. System.out.println("Filtered numbers (without Stream):");
  18. for (Integer number : filteredNumbers) {
  19. System.out.println(number);
  20. }
  21. }
  22. }

输出:

  1. Filtered numbers (without Stream):
  2. 40
  3. 50

使用 Stream 过滤集合示例:

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. public class FilterWithStreamExample {
  4. public static void main(String[] args) {
  5. List<Integer> numbers = new ArrayList<>();
  6. numbers.add(10);
  7. numbers.add(20);
  8. numbers.add(30);
  9. numbers.add(40);
  10. numbers.add(50);
  11. List<Integer> filteredNumbers = numbers.stream()
  12. .filter(number -> number > 30)
  13. .toList();
  14. System.out.println("Filtered numbers (with Stream):");
  15. filteredNumbers.forEach(System.out::println);
  16. }
  17. }

输出:

  1. Filtered numbers (with Stream):
  2. 40
  3. 50

前后我们对比一下,可以看到,使用 Stream 进行集合过滤可以更加简洁和直观,减少了手动迭代和添加元素的步骤。它提供了一种声明式的编程风格,使代码更易读、可维护和可扩展。

5. 使用Stream过滤和遍历集合

在下面的示例中,我们使用 filter() 方法进行过滤,使用 forEach() 方法对数据流进行迭代:

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. public class FilterAndIterateWithStreamExample {
  4. public static void main(String[] args) {
  5. List<String> names = new ArrayList<>();
  6. names.add("Alice");
  7. names.add("Bob");
  8. names.add("Charlie");
  9. names.add("David");
  10. names.add("Eve");
  11. System.out.println("Filtered names starting with 'A':");
  12. names.stream()
  13. .filter(name -> name.startsWith("A"))
  14. .forEach(System.out::println);
  15. }
  16. }

输出

  1. Filtered names starting with 'A':
  2. Alice

在上述示例中,我们有一个字符串列表 names,其中包含了一些名字。
我们使用 Stream 进行过滤和迭代操作以查找以字母 "A" 开头的名字。

6.使用Collectors方法求和

我们还可以使用Collectors计算数值之和。

在下面的示例中,我们使用Collectors类及其指定方法计算所有产品价格的总和。

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import java.util.stream.Collectors;
  4. public class SumByUsingCollectorsMethods {
  5. public static void main(String[] args) {
  6. List < Product > productsList = new ArrayList < Product > ();
  7. productsList.add(new Product(1, "HP Laptop", 25000f));
  8. productsList.add(new Product(2, "Dell Laptop", 30000f));
  9. productsList.add(new Product(3, "Lenevo Laptop", 28000f));
  10. productsList.add(new Product(4, "Sony Laptop", 28000f));
  11. productsList.add(new Product(5, "Apple Laptop", 90000f));
  12. double totalPrice3 = productsList.stream()
  13. .collect(Collectors.summingDouble(product -> product.getPrice()));
  14. System.out.println(totalPrice3);
  15. }
  16. }

输出

  1. 201000.0

7. 使用Stream查找年龄最大和最小的学生

假设有一个 Student 类具有 name 和 age 属性。我们可以使用 Stream 来查找学生集合中年龄的最大和最小值,并打印出相应的学生信息。以下是一个示例:

  1. import java.util.ArrayList;
  2. import java.util.Comparator;
  3. import java.util.List;
  4. import java.util.Optional;
  5. public class StudentStreamExample {
  6. public static void main(String[] args) {
  7. List<Student> students = new ArrayList<>();
  8. students.add(new Student("Alice", 20));
  9. students.add(new Student("Bob", 22));
  10. students.add(new Student("Charlie", 19));
  11. students.add(new Student("David", 21));
  12. // 查找年龄最大的学生
  13. Optional<Student> maxAgeStudent = students.stream()
  14. .max(Comparator.comparingInt(Student::getAge));
  15. // 查找年龄最小的学生
  16. Optional<Student> minAgeStudent = students.stream()
  17. .min(Comparator.comparingInt(Student::getAge));
  18. // 打印最大和最小年龄的学生信息
  19. System.out.println("Student with maximum age:");
  20. maxAgeStudent.ifPresent(System.out::println);
  21. System.out.println("Student with minimum age:");
  22. minAgeStudent.ifPresent(System.out::println);
  23. }
  24. }
  25. class Student {
  26. private String name;
  27. private int age;
  28. public Student(String name, int age) {
  29. this.name = name;
  30. this.age = age;
  31. }
  32. public String getName() {
  33. return name;
  34. }
  35. public int getAge() {
  36. return age;
  37. }
  38. @Override
  39. public String toString() {
  40. return "Student{" +
  41. "name='" + name + '\'' +
  42. ", age=" + age +
  43. '}';
  44. }
  45. }

输出:

  1. Student with maximum age:
  2. Student{name='Bob', age=22}
  3. Student with minimum age:
  4. Student{name='Charlie', age=19}

8. 使用Stream转换List为Map

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import java.util.Map;
  4. import java.util.stream.Collectors;
  5. public class StudentStreamToMapExample {
  6. public static void main(String[] args) {
  7. List<Student> students = new ArrayList<>();
  8. students.add(new Student("Alice", 20));
  9. students.add(new Student("Bob", 22));
  10. students.add(new Student("Charlie", 19));
  11. students.add(new Student("David", 21));
  12. // 将学生列表转换为 Map,以姓名为键,学生对象为值
  13. Map<String, Student> studentMap = students.stream()
  14. .collect(Collectors.toMap(Student::getName, student -> student));
  15. // 打印学生 Map
  16. for (Map.Entry<String, Student> entry : studentMap.entrySet()) {
  17. System.out.println(entry.getKey() + ": " + entry.getValue());
  18. }
  19. }
  20. }
  21. class Student {
  22. private String name;
  23. private int age;
  24. public Student(String name, int age) {
  25. this.name = name;
  26. this.age = age;
  27. }
  28. public String getName() {
  29. return name;
  30. }
  31. public int getAge() {
  32. return age;
  33. }
  34. @Override
  35. public String toString() {
  36. return "Student{" +
  37. "name='" + name + '\'' +
  38. ", age=" + age +
  39. '}';
  40. }
  41. }

输出

  1. David: Student{name='David', age=21}
  2. Bob: Student{name='Bob', age=22}
  3. Charlie: Student{name='Charlie', age=19}
  4. Alice: Student{name='Alice', age=20}

在上面示例中,我们使用Collectors.toMap() 方法将学生列表转换为 Map。我们指定了键提取器 Student::getName,将学生的姓名作为键。对于值提取器,我们使用了一个匿名函数 student -> student,它返回学生对象本身作为值。

9. 使用Stream把List对象转换为另一个List对象

假设我们有一个 Person 类,其中包含姓名和年龄属性。我们可以使用 Stream 来将一个 List 对象转换为另一个 List 对象,其中只包含人员的姓名。以下是一个示例:

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import java.util.stream.Collectors;
  4. public class ListTransformationExample {
  5. public static void main(String[] args) {
  6. List<Person> persons = new ArrayList<>();
  7. persons.add(new Person("Alice", 20));
  8. persons.add(new Person("Bob", 22));
  9. persons.add(new Person("Charlie", 19));
  10. // 将 Person 列表转换为只包含姓名的 String 列表
  11. List<String> names = persons.stream()
  12. .map(Person::getName)
  13. .collect(Collectors.toList());
  14. // 打印转换后的姓名列表
  15. System.out.println(names);
  16. }
  17. }
  18. class Person {
  19. private String name;
  20. private int age;
  21. public Person(String name, int age) {
  22. this.name = name;
  23. this.age = age;
  24. }
  25. public String getName() {
  26. return name;
  27. }
  28. public int getAge() {
  29. return age;
  30. }
  31. }

输出:

  1. [Alice, Bob, Charlie]

在上述示例中,我们有一个 Person 类,其中包含姓名和年龄属性。我们创建了一个 persons 列表,并添加了几个 Person 对象。

使用Stream,我们通过调用 map() 方法并传入一个方法引用 Person::getName,最后,我们使用 collect() 方法和 Collectors.toList() 将转换后的姓名收集到一个新的列表中。

API

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

原文链接:https://www.cnblogs.com/waldron/p/17848756.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号