309. Java Stream API - 非空流(`NONNULL`)

309. Java Stream API - 非空流(NONNULL

在 Java 中,非空流(NONNULL)指的是流中不包含任何 null 元素。
这种流非常适合在数据处理中需要排除 null 值的场景。
许多集合类型和流创建方法会天然地生成非空流。


✅ 创建非空流的常见场景

某些数据结构或方法生成的流会自动带有 Spliterator.NONNULL 特性,这意味着其元素保证不为 null。常见示例如下:

  • 集合类型
    ArrayDequeArrayBlockingQueueConcurrentSkipListSetConcurrentHashMap.newKeySet() 等集合类不允许插入 null 元素,因此它们生成的流天然是非空流。
  • 文件与正则流
    • Files.lines(path):读取文件行时,Stream<String> 中不会出现 null
    • Pattern.splitAsStream(line):根据正则拆分字符串时,也不会产生 null 元素。
  • 注意 Map.values()
    尽管 MapkeySet()entrySet() 通常不包含 null,但 values() 可能包含 null(取决于存入的映射)。
    因此,由 map.values().stream() 创建的流不一定是非空流。

🧩 示例:检查流是否具有 NONNULL 特性

Predicate<Stream<?>> isNonNull =
        stream -> (stream.spliterator().characteristics() & Spliterator.NONNULL) != 0;

Map<Integer, String> hashMap = new HashMap<>();
Collection<String> values = hashMap.values();
System.out.println("Values from hashMap is non-null? " + isNonNull.test(values.stream()));

Collection<String> queue = new ArrayDeque<>();
System.out.println("ArrayDeque is non-null? " + isNonNull.test(queue.stream()));

输出:

Values from hashMap is non-null? false
ArrayDeque is non-null? true

解释:

  1. hashMap.values()Map.values() 可能包含 null 元素,因此其流不具备 NONNULL 特性。
  2. ArrayDeque:该集合禁止 null 元素,因此由它创建的流天然是非空流。

✅ 非空流的特性

🌟 特点

  • 流中的每个元素都保证非空(不为 null)。
  • 通常来自于源头保证不含 null 的集合或数据源。
  • 可通过 Spliterator.NONNULL 标识判断。

🔧 操作特性

  • 保留非空特性
    大部分不会引入新元素的中间操作,如 filter()sorted()distinct() 等,会保留非空特性。
  • 丧失非空特性
    若执行的操作可能引入 null 元素,如 map()flatMap(),则会移除该特性。

💡 示例:不同操作对非空特性的影响

        Predicate<Stream<?>> isNonNull =
                stream -> (stream.spliterator().characteristics() & Spliterator.NONNULL) != 0;

        // 1️⃣ 来自 ArrayDeque —— 不允许 null
        Stream<String> dequeStream = new ArrayDeque<>(List.of("A", "B", "C")).stream();
        System.out.println("ArrayDeque: " + isNonNull.test(dequeStream)); // ✅ true

        // 2️⃣ 来自 ConcurrentHashMap.newKeySet()
        Stream<String> keySetStream = ConcurrentHashMap.<String>newKeySet().stream();
        System.out.println("ConcurrentHashMap.newKeySet: " + isNonNull.test(keySetStream)); // ✅ true

        // 3️⃣ 来自普通 Stream.of(...) —— 不保证 NONNULL
        Stream<String> ofStream = Stream.of("apple", "banana", "cherry");
        System.out.println("Stream.of(...): " + isNonNull.test(ofStream)); // ❌ false

        // 4️⃣ 来自 Files.lines(...) —— 不包含 null
        Path temp = Files.createTempFile("example", ".txt");
        Files.write(temp, List.of("A", "B", "C"));
        Stream<String> fileStream = Files.lines(temp);
        System.out.println("Files.lines(...): " + isNonNull.test(fileStream)); // ✅ true

输出:

ArrayDeque: true
ConcurrentHashMap.newKeySet: true
Stream.of(...): false
Files.lines(...): true

🏁 总结

内容 说明
非空流(NONNULL)定义 流中不包含任何 null 元素
典型来源 不允许 null 的集合(如 ArrayDequeConcurrentHashMap.newKeySet())、Files.lines()Pattern.splitAsStream()
保留特性操作 filter()sorted()distinct()
丧失特性操作 map()flatMap() 等可能引入 null 的操作
判断方法 通过 stream.spliterator().characteristics() 检查是否包含 Spliterator.NONNULL

掌握非空流(NONNULL)的概念与特性,可以在数据处理时更安全、更高效地避免 null 带来的潜在问题,提高代码的健壮性与可读性。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容