Java嵌套Stream跳出循环及区域查找Map构建的优化方案
三级对象区域查找优化方案
编辑说明
- 已将伪代码替换为可运行代码示例。
- SonarLint认为嵌套流可降低认知复杂度,已补充优化结果,感谢@Unmitigated。
需求描述
现有Country、City、District三级对象,Country包含City列表,City包含District列表。需根据名称查找District,并将对应国家、城市、区域信息存入嵌套Map结构。
示例:查找名为"Bastille"的区域,遍历所有国家的所有城市的所有区域,实现逻辑代码如下:
import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; public class Main { public static void main(String[] args) { System.out.println("Hello, World!"); List<Country> countries = new ArrayList<>(); Country co1 = new Country(); co1.setName("USA"); City cit1 = new City(); cit1.setName("New York"); District d1 = new District(); d1.setName("Manhattan"); District d2 = new District(); d2.setName("Queens"); cit1.setDistricts(Arrays.asList(d1, d2)); co1.setCities(Arrays.asList(cit1)); countries.add(co1); Country co2 = new Country(); co2.setName("France"); City cit2 = new City(); cit2.setName("Paris"); District d3 = new District(); d3.setName("Bastille"); District d4 = new District(); d4.setName("Montmarte"); cit2.setDistricts(Arrays.asList(d3, d4)); co2.setCities(Arrays.asList(cit2)); countries.add(co1); countries.add(co2); HashMap<String, HashMap<String, HashMap<String, String>>> foundMap = new HashMap<>(); boolean isFound = method1(countries, foundMap, "Bastille"); System.out.println(foundMap); } public static boolean method1(List<Country> countries, HashMap<String, HashMap<String, HashMap<String, String>>> foundMap, String search) { for(Country country : countries){ for(City city : country.getCities()){ for(District district : city.getDistricts()){ if(district.getName().equals(search)){ if(!foundMap.containsKey(country.getName())){ foundMap.put(country.getName(), new HashMap<>()); } if(!foundMap.get(country.getName()).containsKey(city.getName())){ foundMap.get(country.getName()).put(city.getName(), new HashMap<>()); } foundMap.get(country.getName()).get(city.getName()).put(district.getName(), "Hello from " + district.getName()); return true; } } } } return false; } }
实体类定义
以下是Country、City、District示例类:
Country类
import java.util.List; public class Country { String name; List<City> cities; public String getName() { return name; } public void setName(String name) { this.name = name; } public List<City> getCities() { return cities; } public void setCities(List<City> cities) { this.cities = cities; } }
City类
import java.util.List; public class City { String name; List<District> districts; public String getName() { return name; } public void setName(String name) { this.name = name; } public List<District> getDistricts() { return districts; } public void setDistricts(List<District> districts) { this.districts = districts; } }
District类
public class District { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
运行结果
该示例生成目标Map:{France={Paris={Bastille=Hello from Bastille}}}
实际场景要求
实际场景中,需根据method1的返回值判断,若未找到区域则抛出异常(系统应包含所有区域,未找到视为错误)。同时需要获取国家、城市、区域名称来构建Map条目。
现有问题与困惑
当前代码可实现需求,但SonarLint提示认知复杂度较高,需优化。尝试改用嵌套Stream时,无法实现跳出循环并直接从方法返回结果:
countries.getCities().forEach(city->{ ... ... //若区域名为Bastille return true; //此处返回值无效,仅跳出当前forEach,无法从方法返回 }
寻求更优雅的方式实现区域存在性检查与Map构建逻辑,或确认是否需要调整算法。
优化结论
采用@Unmitigated提供的方案重构代码:
实际场景中原有代码包含4层for循环+判断逻辑,SonarLint检测认知复杂度为30;改用嵌套Stream结合anyMatch,通过内部布尔变量判断并执行Map构建后,认知复杂度降至20。推测SonarLint未统计stream().anyMatch()的复杂度,仅统计for循环,重构后满足公司代码规范要求。
内容的提问来源于stack exchange,提问作者count_campeador
相关产品推荐
相关产品推荐

