Java的Stream流和Option类

1. Stream 流

背景

Stream是Java 8引入的一个用于处理集合(或其他数据源)中的元素的API。它提供了一种声明式的方式来处理数据,并可以链式调用。Stream支持惰性求值,也支持并行流处理。

1.1 创建 Stream

创建一个Stream可以通过多种方式,不同的数据源(如集合、数组、生成器等)提供了不同的创建方法。

1.1.1 使用集合创建 Stream
  • 方法stream() 方法可以用于集合类,如 ListSet 等,返回一个顺序流。

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    Stream<Integer> stream = list.stream();
    stream.forEach(System.out::println); // 输出 1, 2, 3, 4, 5

1.1.2 使用 Arrays 创建 Stream
  • 方法Arrays.stream() 可以从数组创建 Stream。

    int[] numbers = {1, 2, 3, 4, 5};
    IntStream stream = Arrays.stream(numbers);
    stream.forEach(System.out::println); // 输出 1, 2, 3, 4, 5

1.1.3 使用 Stream.of()
  • 方法Stream.of() 创建包含指定元素的Stream。

    Stream<String> stream = Stream.of("Apple", "Banana", "Cherry");
    stream.forEach(System.out::println); // 输出 Apple, Banana, Cherry

1.1.4 使用生成器
  • 方法Stream.generate()Stream.iterate() 用于生成无限流。

    Stream<Double> randomNumbers = Stream.generate(Math::random);
    randomNumbers.limit(5).forEach(System.out::println); // 输出5个随机数

    Stream<Integer> evenNumbers = Stream.iterate(0, n -> n + 2);
    evenNumbers.limit(5).forEach(System.out::println); // 输出 0, 2, 4, 6, 8


1.2 中间操作

中间操作是惰性求值的,它们返回一个新的Stream对象,允许链式调用。常见的中间操作包括 filter(), map(), flatMap(), distinct(), sorted() 等。

1.2.1 filter()
  • 作用:过滤出符合条件的元素。

  • 签名Stream<T> filter(Predicate<? super T> predicate)

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
    System.out.println(evenNumbers); // 输出 [2, 4, 6, 8, 10]

1.2.2 map()
  • 作用:对流中的每个元素应用给定的函数,生成一个新的流。

  • 签名<R> Stream<R> map(Function<? super T, ? extends R> mapper)

    List<String> words = Arrays.asList("hello", "world", "java");
    List<String> upperCaseWords = words.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
    System.out.println(upperCaseWords); // 输出 [HELLO, WORLD, JAVA]

1.2.3 flatMap()
  • 作用:将流中的元素转换成另一个流,然后将多个流合并为一个流。通常用于处理包含集合或数组的流。

  • 签名<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

    List<List<String>> listOfLists = Arrays.asList(
    Arrays.asList("A", "B", "C"),
    Arrays.asList("D", "E", "F")
    );
    List<String> flatList = listOfLists.stream()
    .flatMap(List::stream)
    .collect(Collectors.toList());
    System.out.println(flatList); // 输出 [A, B, C, D, E, F]

1.2.4 distinct()
  • 作用:去重,返回一个只包含不同元素的流。

  • 签名Stream<T> distinct()

    List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
    List<Integer> distinctNumbers = numbers.stream()
    .distinct()
    .collect(Collectors.toList());
    System.out.println(distinctNumbers); // 输出 [1, 2, 3, 4, 5]

1.2.5 sorted()
  • 作用:对流中的元素进行排序。

  • 签名Stream<T> sorted()

    List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 3);
    List<Integer> sortedNumbers = numbers.stream()
    .sorted()
    .collect(Collectors.toList());
    System.out.println(sortedNumbers); // 输出 [1, 2, 3, 5, 8]

1.2.6 anyMatch(), allMatch(), noneMatch()
  • 作用:这些方法用于匹配流中的元素:

    • anyMatch() 检查流中是否至少有一个元素满足条件。
    • allMatch() 检查流中的所有元素是否都满足条件。
    • noneMatch() 检查流中是否没有元素满足条件。
  • 签名

    • boolean anyMatch(Predicate<? super T> predicate)

    • boolean allMatch(Predicate<? super T> predicate)

    • boolean noneMatch(Predicate<? super T> predicate)

      List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
      boolean anyGreaterThan3 = numbers.stream().anyMatch(n -> n > 3); // true
      boolean allGreaterThan0 = numbers.stream().allMatch(n -> n > 0); // true
      boolean noneNegative = numbers.stream().noneMatch(n -> n < 0); // true
      System.out.println(anyGreaterThan3); // 输出 true
      System.out.println(allGreaterThan0); // 输出 true
      System.out.println(noneNegative); // 输出 true

1.2.7 peek()
  • 作用peek() 用于在中间操作中查看流中的每个元素。通常用于调试。

  • 签名Stream<T> peek(Consumer<? super T> action)

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    List<Integer> result = numbers.stream()
    .peek(n -> System.out.println("Before filter: " + n))
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());


1.3 终止操作

终止操作会触发流的处理,并生成一个最终的结果或副作用。常见的终止操作包括 collect(), forEach(), reduce(), count(), min() 等。

1.3.1 collect()
  • 作用:将流转换为集合或其他类型的结果。

  • 签名<R, A> R collect(Collector<? super T, A, R> collector)

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
    System.out.println(evenNumbers); // 输出 [2, 4]

1.3.2 forEach()
  • 作用:对流中的每个元素执行给定的操作。

  • 签名void forEach(Consumer<? super T> action)

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    numbers.stream()
    .forEach(n -> System.out.println(n)); // 输出 1, 2, 3, 4, 5

1.3.3 reduce()
  • 作用:将流中的元素结合成一个单一的结果,常用于求和、求积等操作。

  • 签名T reduce(T identity, BinaryOperator<T> accumulator)

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    int sum = numbers.stream()
    .reduce(0, (a, b) -> a + b);
    System.out.println(sum); // 输出 15

1.3.4 count()
  • 作用:计算流中的元素个数。

  • 签名long count()

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    long count = numbers.stream()
    .filter(n -> n % 2 == 0)
    .count();
    System.out.println(count); // 输出 2

1.3.5 min() 和 max()
  • 作用:找到流中的最小值或最大值。

  • 签名Optional<T> min(Comparator<? super T> comparator)

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    Optional<Integer> min = numbers.stream()
    .min(Integer::compare);
    System.out.println(min.get()); // 输出 1

1.3.6 findFirst() 和 findAny()
  • 作用 :这两个方法用于获取流中的元素。
    • findFirst() 返回第一个元素。

    • findAny() 返回任意元素(并行流时表现不同)。

      List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
      Optional<Integer> first = numbers.stream().findFirst();
      Optional<Integer> any = numbers.stream().findAny();
      System.out.println(first.get()); // 输出 1
      System.out.println(any.get()); // 输出 任意一个数


总结
  • Stream 提供了更简洁、声明式的方式处理数据流。
  • 中间操作如 filter(), map(), flatMap() 等支持链式操作,实现强大的数据处理能力。
  • 终止操作则触发最终的处理过程,如 collect(), forEach(), reduce() 等。

2. Optional 类

背景

Optional 是 Java 8 引入的一个容器类,用于解决传统 null 引用带来的 NullPointerException 问题。它表示一个可能为 null 的值,而不是直接使用 null,通过提供多种方法使得 Optional 的值可以更安全地处理。

Optional 主要用于以下几种场景:

  • 避免 null :避免直接返回或传递 null,提高代码的可读性和安全性。
  • 链式操作 :允许对可能为 null 的值进行安全的链式调用,而不必担心 NullPointerException

2.1 创建 Optional

2.1.1 Optional.of()
  • 作用 :创建一个非空的 Optional,如果值为 null,则抛出 NullPointerException

  • 签名static <T> Optional<T> of(T value)

    Optional<String> optional = Optional.of("Hello");
    System.out.println(optional.get()); // 输出 Hello

  • 注意 :传入 null 会抛出异常。

    Optional<String> optional = Optional.of(null); // 会抛出 NullPointerException

2.1.2 Optional.ofNullable()
  • 作用 :创建一个 Optional,如果值为 null,则返回一个空的 Optional

  • 签名static <T> Optional<T> ofNullable(T value)

    Optional<String> optional = Optional.ofNullable("Hello");
    System.out.println(optional.get()); // 输出 Hello

    Optional<String> emptyOptional = Optional.ofNullable(null);
    System.out.println(emptyOptional.isPresent()); // 输出 false

2.1.3 Optional.empty()
  • 作用 :创建一个空的 Optional 对象。

  • 签名static <T> Optional<T> empty()

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.isPresent()); // 输出 false


2.2 常用方法

2.2.1 isPresent()
  • 作用 :检查 Optional 是否包含一个非空的值。

  • 签名boolean isPresent()

    Optional<String> optional = Optional.of("Hello");
    System.out.println(optional.isPresent()); // 输出 true

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.isPresent()); // 输出 false

2.2.2 ifPresent()
  • 作用 :如果 Optional 中有值,则执行给定的操作;如果没有值,则什么也不做。

  • 签名void ifPresent(Consumer<? super T> action)

    Optional<String> optional = Optional.of("Hello");
    optional.ifPresent(System.out::println); // 输出 Hello

    Optional<String> emptyOptional = Optional.empty();
    emptyOptional.ifPresent(System.out::println); // 不输出任何内容

2.2.3 get()
  • 作用 :获取 Optional 中的值,如果值不存在,会抛出 NoSuchElementException

  • 签名T get()

    Optional<String> optional = Optional.of("Hello");
    System.out.println(optional.get()); // 输出 Hello

    Optional<String> emptyOptional = Optional.empty();
    // emptyOptional.get(); // 会抛出 NoSuchElementException

2.2.4 orElse()
  • 作用 :如果 Optional 中有值,返回该值;如果没有值,返回提供的默认值。

  • 签名T orElse(T other)

    Optional<String> optional = Optional.of("Hello");
    System.out.println(optional.orElse("Default Value")); // 输出 Hello

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.orElse("Default Value")); // 输出 Default Value

2.2.5 orElseGet()
  • 作用 :与 orElse() 类似,但 orElseGet() 使用 Supplier 提供默认值,这样可以延迟计算。

  • 签名T orElseGet(Supplier<? extends T> supplier)

    Optional<String> optional = Optional.of("Hello");
    System.out.println(optional.orElseGet(() -> "Default Value")); // 输出 Hello

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.orElseGet(() -> "Default Value")); // 输出 Default Value

2.2.6 orElseThrow()
  • 作用 :如果 Optional 中有值,返回该值;如果没有值,抛出指定的异常。

  • 签名T orElseThrow(Supplier<? extends X> exceptionSupplier)

    Optional<String> optional = Optional.of("Hello");
    System.out.println(optional.orElseThrow(() -> new IllegalArgumentException("Value is missing"))); // 输出 Hello

    Optional<String> emptyOptional = Optional.empty();
    // emptyOptional.orElseThrow(() -> new IllegalArgumentException("Value is missing")); // 会抛出 IllegalArgumentException

2.2.7 map()
  • 作用 :如果 Optional 中有值,应用给定的映射函数返回一个新的 Optional,如果没有值,则返回一个空的 Optional

  • 签名<U> Optional<U> map(Function<? super T, ? extends U> mapper)

    Optional<String> optional = Optional.of("Hello");
    Optional<String> upperCaseOptional = optional.map(String::toUpperCase);
    System.out.println(upperCaseOptional.get()); // 输出 HELLO

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.map(String::toUpperCase).isPresent()); // 输出 false

2.2.8 flatMap()
  • 作用 :类似于 map(),但 flatMap() 返回的是一个 Optional。通常用于处理返回值本身可能为 Optional 的情况。

  • 签名<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

    Optional<String> optional = Optional.of("Hello");
    Optional<String> result = optional.flatMap(value -> Optional.of(value.toUpperCase()));
    System.out.println(result.get()); // 输出 HELLO

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.flatMap(value -> Optional.of(value.toUpperCase())).isPresent()); // 输出 false

2.2.9 filter()
  • 作用 :如果 Optional 中有值并且满足给定的条件,则返回一个包含该值的 Optional,否则返回一个空的 Optional

  • 签名Optional<T> filter(Predicate<? super T> predicate)

    Optional<Integer> optional = Optional.of(5);
    Optional<Integer> result = optional.filter(n -> n > 3);
    System.out.println(result.get()); // 输出 5

    Optional<Integer> result2 = optional.filter(n -> n < 3);
    System.out.println(result2.isPresent()); // 输出 false

2.2.10 ifPresentOrElse()
  • 作用 :如果 Optional 中有值,执行给定的操作,否则执行提供的另一个操作。

  • 签名void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)

    Optional<String> optional = Optional.of("Hello");
    optional.ifPresentOrElse(
    value -> System.out.println("Value: " + value), // 输出 Value: Hello
    () -> System.out.println("Value is absent")
    );

    Optional<String> emptyOptional = Optional.empty();
    emptyOptional.ifPresentOrElse(
    value -> System.out.println("Value: " + value),
    () -> System.out.println("Value is absent") // 输出 Value is absent
    );


2.3 使用场景

2.3.1 使用 Optional 返回可能为 null 的值

在方法中返回 Optional 而非直接返回 null,避免客户端代码中直接进行 null 值检查。

public Optional<String> findUserById(int userId) {
    User user = userRepository.findById(userId);
    return Optional.ofNullable(user != null ? user.getName() : null);
}

Optional<String> name = findUserById(1);
name.ifPresent(System.out::println);  // 如果值存在,打印用户名
2.3.2 使用 Optional 简化链式调用

Optional 可以避免 null 检查,并通过 map()flatMap()filter() 等方法方便地进行链式调用。

public Optional<Address> getUserAddress(User user) {
    return Optional.ofNullable(user)
                   .map(User::getAddress);
}

Optional<Address> address = getUserAddress(user);
address.ifPresent(addr -> System.out.println("Address: " + addr.getStreet()));

总结

  • Optional 提供了一种优雅的方式来处理可能为 null 的值,避免了 NullPointerException
  • 常用方法如 map()filter()ifPresent()orElse()orElseThrow() 等,使得对 Optional 的操作更加简洁且安全。
  • 使用 Optional 可以有效提高代码的可读性和可维护性,尤其是在返回可能为 null 的值时。

通过理解和使用 Optional,可以显著降低出现空指针异常的风险,优化代码的健壮性。

相关推荐
李歘歘8 分钟前
Golang——GPM调度器
java·开发语言·后端·golang·go·秋招·春招
再拼一次吧10 分钟前
final修饰的用法
java·开发语言·jvm
计算机-秋大田10 分钟前
基于微信小程序的电影交流平台设计与实现(LW+源码+讲解)
java·微信小程序·小程序·课程设计
多多*12 分钟前
初识JVM HotSopt 的发展历程
java·开发语言·jvm·c++·学习·算法
chian-ocean35 分钟前
进程的家园:探索 Linux 地址空间的奥秘
android·java·linux
c1assy1 小时前
天机学堂3-ES+Caffeine
android·java·elasticsearch
終不似少年遊*1 小时前
通过一个算法的设计来了解栈的一些应用
java·前端·数据库
军训猫猫头1 小时前
43.Textbox的数据绑定 C#例子 WPF例子
java·c#·wpf
多多*3 小时前
线程池相关 FutureTask介绍 处理阻塞 Future改进->CompletableFuture
java·开发语言·后端·python·spring
画船听雨眠aa3 小时前
Spring框架(三)ioc注解与junit单元测试整合
java·spring