首页
Preview

Java Stream API 速查表:

Java Stream API 有以下重要的方法:

Java Stream 是一系列函数或操作的流水线。这些操作可以分为两种类型:

  • Intermediate Operation(中间操作)
  • Terminal Operation(终止操作)

两者之间的区别在于操作创建的输出。如果一个操作输出另一个流,你可以对其应用进一步的操作,我们称之为中间操作。然而,如果操作输出具体类型或产生副作用,则为终止类型。

显然,终止操作后面不能跟随后续流操作,因为终止操作不返回流!

中间操作

中间操作总是懒执行。也就是说,它们不会运行,直到达到终止操作的点。我们将深入了解流中使用的几个最受欢迎的中间操作。

  • map — map 操作返回经过传递给该操作的函数处理后的元素流。映射之前和之后的元素可能具有不同的类型,但元素的总数将保持不变。
  • filter — filter 操作返回满足传递给该操作的谓词的元素流。在过滤之前和之后,元素本身将具有相同的类型,但元素的数量可能会改变。
  • distinct — distinct 操作是 filter 操作的特例。基于元素的 equals 方法,distinct 返回一个流,使得流中的每个元素都是唯一的。

下面是一个总结表格,包括一些其他常见的中间操作。

终止操作

终止操作总是急切执行。该操作将启动流中存在的所有先前的惰性操作的执行。终止操作要么返回具体类型,要么产生副作用。例如,调用 Integer::sum 操作的 reduce 操作将生成一个 Optional,它是一个具体类型。另外,forEach 操作不返回具体类型,但你可以添加一个副作用,例如打印每个元素。collect 终止操作是 reduce 的一种特殊类型,它获取流中的所有元素,并可以生成一个 SetMapList。下面是一个表格总结。

流的示例

练习1:从字符串数字列表中获取偶数。

List<String> numbers = Arrays.asList("1", "2", "3", "4", "5", "6");//Convert list of string to even number listList<Integer> even = numbers.stream()
                                .map(s -> Integer.valueOf(s))
                                .filter(number -> number % 2 == 0)
                                .collect(Collectors.toList());

练习2:获取50岁或以上的前15个书籍作者的大写姓氏的唯一值。

List<String> surname =
           library.stream()
           .map(book -> book.getAuthor())
           .filter(author -> author.getAge() >= 50)
           .map(Author::getSurname)
           .map(String::toUpperCase)
           .distinct()
           .limit(15)
           .collect(toList()));

我们的流源 library 是一个 ArrayList。查看代码并跟随说明。从这个书籍列表中,我们首先需要从书籍到书籍作者的映射,这给我们一个 Authors 流,然后将它们过滤为只获取那些50岁或以上的作者。我们将 Author 的姓映射为 Strings,这将给我们一个 Strings 流。我们将其映射为大写的 Strings,并确保流中的元素是唯一的,并获取前15个。最后,我们使用 java.util.streams.Collectors 中的 toList 将其作为列表返回。

练习3:打印出所有年龄小于25岁的女性作者的年龄总和。

int sum = library.stream()
          .map(Book::getAuthor)
          .filter(author -> author.getGender() == Gender.FEMALE)
          .map(Author::getAge)
          .filter(age -> age < 25)
          .reduce(0, Integer::sum)

使用相同的原始流,我们再次将元素从 Books 映射到 Authors,并仅对女性作者进行过滤。接下来,我们将元素从 Authors 映射到作者年龄,这给我们一个 int 流。我们将年龄过滤为小于25岁的年龄,并使用 reduce 操作和 Integer::sum 来计算年龄总和。

练习4:返回第一个薪资大于100000的员工。如果不存在这样的员工,则返回 null

Employee employee = 
      Stream.of(empIds)
      .map(employeeRepository::findById)
      .filter(e -> e != null)
      .filter(e -> e.getSalary() > 100000)
      .findFirst()
      .orElse(null);

练习4:将流转换为数组。

Employee[] employees = empList.stream().toArray(Employee[]::new);

包装和解包

有时,我们需要将基本值转换为其包装器等效项。

在这些情况下,我们可以使用 boxed() 方法:

List<Integer> evenInts = IntStream.rangeClosed(1, 10)
  .filter(i -> i % 2 == 0)
  .boxed()
  .collect(Collectors.toList());

我们还可以从包装类流转换为基本流:

// returns 78
int sum = Arrays.asList(33,45)
  .stream()
  .mapToInt(i -> i)
  .sum();

我们总是可以使用 mapToXxxflatMapToXxx 方法创建基本流。

Java Stream 的创建

让我们首先从现有数组中获取流:

private static Employee[] arrayOfEmps = {
    new Employee(1, "Jeff Bezos", 100000.0), 
    new Employee(2, "Bill Gates", 200000.0), 
    new Employee(3, "Mark Zuckerberg", 300000.0)
};Stream.of(arrayOfEmps);

我们还可以从现有列表中获取流:

private static List<Employee> empList = Arrays.asList(arrayOfEmps);
empList.stream();

请注意,Java 8 添加了一个新的 stream() 方法到 Collection 接口。

我们还可以使用 Stream.of() 从单个对象创建流:

Stream.of(arrayOfEmps[0], arrayOfEmps[1], arrayOfEmps[2]);

或者简单地使用 Stream.builder()

Stream.Builder<Employee> empStreamBuilder = Stream.builder();empStreamBuilder.accept(arrayOfEmps[0]);
empStreamBuilder.accept(arrayOfEmps[1]);
empStreamBuilder.accept(arrayOfEmps[2]);Stream<Employee> empStream = empStreamBuilder.build();

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
阿波
The minute I see you, I want your clothes gone!

评论(0)

添加评论