Java Stream flatMap
最后修改于 2025 年 5 月 24 日
本文演示了如何使用 Java Stream flatMap 方法来转换和扁平化嵌套数据结构。
flatMap 是一个中间流操作,它将每个元素映射到一个流,然后将这些流扁平化成一个单一的流。 它在处理嵌套集合或当每个元素可以被转换成多个元素时特别有用。
基本的 flatMap 语法
flatMap
的方法签名是
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
mapper 函数接受一个 T 类型的元素并返回一个 R 类型的 Stream。flatMap 操作然后将所有这些流连接成一个单一的流。
扁平化嵌套集合
flatMap 最常见的用例是扁平化嵌套集合。
void main() { List<List<String>> nestedLists = List.of( List.of("a", "b", "c"), List.of("d", "e"), List.of("f", "g", "h", "i") ); Stream<String> flattened = nestedLists.stream() .flatMap(List::stream); flattened.forEach(System.out::println); }
这个例子接受一个列表的列表,并将其扁平化成一个单一的字符串流。List::stream 方法引用将每个内部列表转换为一个流,而 flatMap 将它们组合起来。
转换和扁平化
flatMap 可以同时转换元素和扁平化结果。
void main() { List<Integer> numbers = List.of(1, 2, 3, 4); Stream<Integer> doubled = numbers.stream() .flatMap(n -> Stream.of(n, n * 2)); doubled.forEach(System.out::println); }
这个例子接受每个数字,并将其映射到一个包含原始数字及其两倍的流。flatMap 操作然后将所有这些流组合起来。
处理可选值
flatMap 对于过滤掉空的 Optional 值同时提取值非常有用。
void main() { List<Optional<String>> options = List.of( Optional.of("apple"), Optional.empty(), Optional.of("banana"), Optional.empty(), Optional.of("cherry") ); Stream<String> fruits = options.stream() .flatMap(Optional::stream); fruits.forEach(System.out::println); }
这个例子过滤掉空的 Optionals,并从存在的 Optionals 中提取值。Optional::stream
方法将一个 Optional
转换成一个包含 0 或 1 个元素的流。
将字符串拆分成单词
flatMap 可以用来分割字符串,并将所有单词组合成一个流。
void main() { List<String> sentences = List.of( "Hello there", "Java streams are powerful", "flatMap is useful" ); Stream<String> words = sentences.stream() .flatMap(s -> Stream.of(s.split(" "))); words.forEach(System.out::println); }
这个例子将每个句子分割成单词,并将所有句子中的所有单词组合成一个单一的流。lambda 表达式通过空格分割每个字符串。
$ java Main.java Hello there Java streams are powerful flatMap is useful
使用嵌套对象
flatMap 对于从对象中提取嵌套集合非常有用。
record Order(String id, List<String> items) { } void main() { List<Order> orders = List.of( new Order("001", List.of("Shirt", "Pants")), new Order("002", List.of("Shoes", "Socks", "Hat")), new Order("003", List.of("Jacket")) ); Stream<String> allItems = orders.stream() .flatMap(order -> order.items().stream()); allItems.forEach(System.out::println); }
这个例子将所有订单中的所有商品提取到一个单一的流中。每个订单的商品都被转换成一个流,然后被扁平化。
$ java Main.java Shirt Pants Shoes Socks Hat Jacket
组合多个流
flatpMap
可以组合来自多个源的元素。
void main() { Stream<String> stream1 = Stream.of("A", "B", "C"); Stream<String> stream2 = Stream.of("X", "Y", "Z"); Stream<Stream<String>> nested = Stream.of(stream1, stream2); Stream<String> combined = nested.flatMap(s -> s); combined.forEach(System.out::println); }
这个例子使用 flatMap
将两个独立的流组合成一个。请注意,一旦一个流被消耗(例如在 flatMap 操作中),它就不能被重用。
生成笛卡尔积
flatMap 可以用来生成集合的笛卡尔积。
void main() { List<String> colors = List.of("Red", "Green", "Blue"); List<String> sizes = List.of("S", "M", "L"); Stream<String> products = colors.stream() .flatMap(color -> sizes.stream() .map(size -> color + " " + size) ); products.forEach(System.out::println); }
这个例子生成颜色和大小的所有可能组合。每种颜色都使用嵌套的 flatMap 和 map 操作与每个大小配对。
$ java Main.java Red S Red M Red L Green S Green M Green L Blue S Blue M Blue L
flatMap 与原始类型流
你可以使用 flatMapToInt
、flatMapToDouble
或 flatMapToLong
来扁平化和处理数字集合。例如,你可以将表示数字的字符串列表转换成一个单一的 IntStream
。
void main() { List<String> numberStrings = List.of("1,2,3", "4,5", "6"); IntStream numbers = numberStrings.stream() .flatMapToInt(s -> Arrays.stream(s.split(",")).mapToInt(Integer::parseInt)); numbers.forEach(System.out::println); }
这个例子通过逗号分割每个字符串,解析数字,并将它们扁平化成一个单一的 IntStream
。
解析和扁平化 CSV 数据
flatMap 可以用来解析 CSV 字符串列表,提取字段,并将它们扁平化成一个单一的流以进行进一步处理。
record User(String firstName, String lastName, int age) { } void main() { List<String> csvRows = List.of("John,Doe,30", "Jane,Smith,25", "Bob,Johnson,40"); Stream<User> users = csvRows.stream() .map(row -> row.split(",")) // Split row .map(fields -> new User(fields[0], fields[1], Integer.parseInt(fields[2]))); // Convert to User users.forEach(System.out::println); }
该示例演示了如何解析 CSV 数据,其中每一行被拆分为字段,然后每个字段用于创建一个 User
对象。这里没有显式使用 flatMap 方法,但是如果你想扁平化嵌套结构或组合多个用户流,可以应用它。
来源
在本文中,我们探讨了 Java Stream flatMap
方法。它是一个强大的工具,用于处理嵌套数据结构,组合多个流,并在扁平化结果的同时转换元素。
作者
列出所有Java教程。