编辑:将伪代码切换为可运行的代码示例。
编辑2:Sonarlink认为嵌套流降低了认知复杂性,在我的问题末尾添加了结果。谢谢@ Unamended。
我有一些对象,让说;国家,城市,地区。国家有城市列表,城市有地区列表。
我试图找到一个地区的名称,并把这些数据在Map上。
例如:区名是“巴士底”。2我试图通过检查所有国家、所有城市、所有区来找到它。3下面是我的逻辑的示例代码。
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;
}
}
这里有国家、城市、地区类的样本;
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;
}
}
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;
}
}
public class District {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
这个例子为我创建了所需的HashMap;
巴黎:你好,巴士底狱
在我的情况下,我需要检查method 1的返回,如果没有找到这个地区,就抛出一个异常!(系统应该包含所有的地区,所以“没有找到”是一个失败)
我还需要所有这些国家名、城市名、地区名(这些嵌套的for循环提供给我)来创建这个HashMap条目。
那么有没有更优雅的方法来用流或其他工具实现这种逻辑呢?(我对这段代码没问题,但sonarlint对“认知复杂性”不满意,我必须找到一种方法来降低它)。
尝试切换到嵌套流,但我不知道如何在这里使用流。我可以使用一些嵌套流,但我无法返回true。
countries.getCities().forEach(city->{
...
...
//if district name is Bastille
return true; //Unexpected Return value because this is inside nested streams, not returning true from the method. If only "return" is used, I only returns from iterable to the outer stream.
}
那么,有没有更好的方法来使“检查是否存在区域”和“将所有数据放入散列表”逻辑运行?或者解决这个问题的唯一方法是改变算法?
结论:我把我的代码切换到Unamended的答案。
在我的真实的情况中,我必须创建4个“for”循环,然后是一个“if”来检查条件是否满足,然后是一些带有hashmap的业务逻辑。Sonarlink认为方法的认知复杂度是30。
在切换到使用anyMatch的嵌套流之后,一个内部布尔变量检查是否满足条件,然后使用hashmap和返回的一些业务逻辑;Sonarlink现在说认知复杂度下降到了20。我认为这是Sonarlink的误判,因为它忽略了“stream().anyMatch(...”,但却把“for(Obj o:列表)”。
问题是:我的公司不允许在方法中有更高级别的复杂性,在此重构Sonarlink后很高兴。
1条答案
按热度按时间roejwanj1#
您可以使用嵌套的
Stream#anyMatch
(这是一种短路操作),但它并不能真正降低认知复杂性。