文章目录
- 275. Java Stream API - flatMap 操作:展开一对多的关系,拉平你的流!
- 🧠 背景:我们为什么需要 `flatMap`?
- 🔁 用 `flatMap` 优雅替代嵌套循环
- ✅ 定义模型结构
- ✅ 初始化数据
- 🚀 使用 `flatMap` 重写统计逻辑
- 🔍 `flatMap` 是如何工作的?
- 步骤 1️⃣:映射(map)
- 步骤 2️⃣:展平(flat)
- 📚 延伸案例:`Map` 结构的 `flatMap`
- 🧠 小结:`flatMap` 用法口诀
- 🧪 练习建议(课堂可选)
- ❓ 问题:下面代码的输出是什么?
275. Java Stream API - flatMap 操作:展开一对多的关系,拉平你的流!
🧠 背景:我们为什么需要flatMap?
假设我们有以下结构:
- 每个
Country拥有多个City - 每个
City有一个人口数population
我们的目标是:统计所有城市的总人口数。
最直接的写法当然是嵌套 for 循环:
inttotalPopulation=0;for(Countrycountry:countries){for(Citycity:country.cities()){totalPopulation+=city.population();}}System.out.println("Total population = "+totalPopulation);📌 输出:
Totalpopulation=24493虽然有效,但Java 8之后我们有了更优雅的方式:使用流 +flatMap来处理一对多的关系。
🔁 用flatMap优雅替代嵌套循环
✅ 定义模型结构
recordCity(Stringname,intpopulation){}recordCountry(Stringname,List<City>cities){}✅ 初始化数据
CitynewYork=newCity("New York",8_258);CitylosAngeles=newCity("Los Angeles",3_821);Countryusa=newCountry("USA",List.of(newYork,losAngeles));Citylondon=newCity("London",8_866);Citymanchester=newCity("Manchester",568);Countryuk=newCountry("United Kingdom",List.of(london,manchester));Cityparis=newCity("Paris",2_103);Citymarseille=newCity("Marseille",877);Countryfrance=newCountry("France",List.of(paris,marseille));List<Country>countries=List.of(usa,uk,france);🚀 使用flatMap重写统计逻辑
inttotalPopulation=countries.stream().flatMap(country->country.cities().stream())// 展开所有城市.mapToInt(City::population)// 提取人口.sum();// 累加总人口System.out.println("Total population = "+totalPopulation);📌 输出:
Totalpopulation=24493🔍flatMap是如何工作的?
flatMap是两个操作的组合:
步骤 1️⃣:映射(map)
country->country.cities().stream()这一步将每个Country映射为它的城市流,得到的是一个Stream<Stream<City>>(流的流)。
步骤 2️⃣:展平(flat)
flatMap会自动帮你把多个子流合并为一个连续的扁平流(Stream<City>),这样你就可以对所有城市统一处理!
🎯 类比图示:
Stream<Country>---映射--->Stream<Stream<City>>|+--->展平(flatten)--->Stream<City>📚 延伸案例:Map结构的flatMap
假设我们有一个Continent类型,它包含一个 Map:
recordContinent(Map<String,Country>countries){}此时,如果你想从Continent中提取所有国家,可以这样写:
Function<Continent,Stream<Country>>continentToCountry=continent->continent.countries().values().stream();再进一步,还可以这样嵌套flatMap:
inttotal=continents.stream().flatMap(continent->continent.countries().values().stream()).flatMap(country->country.cities().stream()).mapToInt(City::population).sum();🧠 小结:flatMap用法口诀
| 用法场景 | 对应方法 |
|---|---|
| 一对一映射(每个元素 → 单个新值) | .map() |
| 一对多映射(每个元素 → 多个新值) | .flatMap() |
| 提取嵌套集合中的内容并扁平化 | .flatMap() |
转换成基础类型流(int/long/double) | .mapToInt()等 |
🧪 练习建议(课堂可选)
❓ 问题:下面代码的输出是什么?
List<String>words=List.of("java","stream","api");List<Character>chars=words.stream().flatMap(word->word.chars().mapToObj(c->(char)c)).toList();System.out.println(chars);🎯 答案:
[j,a,v,a,s,t,r,e,a,m,a,p,i]