Java 8 分组并追加到一个集合
Java 8 Group by and append to a set
我有 return 一个 Map<String, Set<String>>
的函数,java 8 之前的代码:
Map<String, Set<String>> degreeMap = new HashMap<>();
for(Course course : courses){
Set<String> cList = degreeMap.get(course.getCourseLevel().toString());
if(Objects.nonNull(cList)){
cList.addAll(course.getMasterDegree()); //this is what i want to append to the old set
degreeMap.put(course.getCourseLevel().toString(), cList);
} else{
degreeMap.put(course.getCourseLevel().toString(), new HashSet<>(course.getMasterDegree()));
}
}
return degreeMap;
其中 return 课程级别 -> 度数的地图。
例如,它读取了所有课程和 return 地图,例如:
{"undergraduate" : ["BTech", "BSc", "BE"],
"masters": ["MTech", "MBA"],
"Executive": ["PGDBM", "EECP"]}
这是我的课程class:
public class Course {
private List<String> masterDegree;
private CourseLevel courseLevel;
}
但是我想把这段代码写成Java8风格。为此,我尝试了这个:
Map<String, Set<String>> degreeMap = courses.stream().collect(
Collectors.groupingBy(c -> c.getCourseLevel().toString(),
Collectors.mapping(c -> c.getMasterDegree(), Collectors.toSet()))
);
这是行不通的,我收到以下编译时错误:
no instance(s) of type variable(s) exist so that List conforms to String inference variable T has incompatible bounds: equality constraints: String lower bounds: List
有什么建议,如何实现?
我认为您不需要 lambda 表达式,您应该重构代码以使其更清晰。
// supposed to be initialied with non-empty values
// Map<String, Set<String>> degreeMap = ...
for(Course course : courses){
// something like below
String key = course.getCourseLevel().toString();
// degreeSet should not be null
Set<String> degreeSet = course.getMasterDegree();
// TODO: check nullable
degreeSet.putAll(degreeMap.get(key));
degreeMap.put(key, degreeSet);
}
return degreeMap;
未经测试,但看起来您正在寻找类似的东西:
return courses.stream()
.collect(Collectors.toMap(course -> course.getCourseLevel().toString(),
course -> new HashSet<>(course.getMasterDegree()),
(set1, set2) -> Stream.of(set1, set2)
.flatMap(Set::stream).collect(Collectors.toSet())));
您可能对 Collectors.toMap() 方法感兴趣。
这是一个您可能需要调整的示例,因为我没有对其进行测试。
Map<String, Set<String>> degreeMap = courses.stream()
.collect(
Collectors.toMap(
item -> item.getCourseLevel().toString(), //your key mapping
item -> item.getMasterDegree(), //your value mapping
(oldValue, newValue) -> { //your process of aggregation
if (null == oldValue) {
return newValue;
} else {
oldValue.addAll(newValue);
return oldValue;
}
},
LinkedHashMap::new //your result initialiser
)
);
另外,还有一个小技巧:不需要按键获取和检查是否为null,可以使用地图上的.compute()、.computeIfAbsent()、.computeIfPresent()方法
我有 return 一个 Map<String, Set<String>>
的函数,java 8 之前的代码:
Map<String, Set<String>> degreeMap = new HashMap<>();
for(Course course : courses){
Set<String> cList = degreeMap.get(course.getCourseLevel().toString());
if(Objects.nonNull(cList)){
cList.addAll(course.getMasterDegree()); //this is what i want to append to the old set
degreeMap.put(course.getCourseLevel().toString(), cList);
} else{
degreeMap.put(course.getCourseLevel().toString(), new HashSet<>(course.getMasterDegree()));
}
}
return degreeMap;
其中 return 课程级别 -> 度数的地图。
例如,它读取了所有课程和 return 地图,例如:
{"undergraduate" : ["BTech", "BSc", "BE"],
"masters": ["MTech", "MBA"],
"Executive": ["PGDBM", "EECP"]}
这是我的课程class:
public class Course {
private List<String> masterDegree;
private CourseLevel courseLevel;
}
但是我想把这段代码写成Java8风格。为此,我尝试了这个:
Map<String, Set<String>> degreeMap = courses.stream().collect(
Collectors.groupingBy(c -> c.getCourseLevel().toString(),
Collectors.mapping(c -> c.getMasterDegree(), Collectors.toSet()))
);
这是行不通的,我收到以下编译时错误:
no instance(s) of type variable(s) exist so that List conforms to String inference variable T has incompatible bounds: equality constraints: String lower bounds: List
有什么建议,如何实现?
我认为您不需要 lambda 表达式,您应该重构代码以使其更清晰。
// supposed to be initialied with non-empty values
// Map<String, Set<String>> degreeMap = ...
for(Course course : courses){
// something like below
String key = course.getCourseLevel().toString();
// degreeSet should not be null
Set<String> degreeSet = course.getMasterDegree();
// TODO: check nullable
degreeSet.putAll(degreeMap.get(key));
degreeMap.put(key, degreeSet);
}
return degreeMap;
未经测试,但看起来您正在寻找类似的东西:
return courses.stream()
.collect(Collectors.toMap(course -> course.getCourseLevel().toString(),
course -> new HashSet<>(course.getMasterDegree()),
(set1, set2) -> Stream.of(set1, set2)
.flatMap(Set::stream).collect(Collectors.toSet())));
您可能对 Collectors.toMap() 方法感兴趣。
这是一个您可能需要调整的示例,因为我没有对其进行测试。
Map<String, Set<String>> degreeMap = courses.stream()
.collect(
Collectors.toMap(
item -> item.getCourseLevel().toString(), //your key mapping
item -> item.getMasterDegree(), //your value mapping
(oldValue, newValue) -> { //your process of aggregation
if (null == oldValue) {
return newValue;
} else {
oldValue.addAll(newValue);
return oldValue;
}
},
LinkedHashMap::new //your result initialiser
)
);
另外,还有一个小技巧:不需要按键获取和检查是否为null,可以使用地图上的.compute()、.computeIfAbsent()、.computeIfPresent()方法