[英]Filter out values when converting List<SomeObject> to Map<String, Set<String>> using Java 8 streams API
这个问题涉及到这个问题的SO
我有一个学生班的实例。
class Student {
String name;
String addr;
String type;
public Student(String name, String addr, String type) {
super();
this.name = name;
this.addr = addr;
this.type = type;
}
@Override
public String toString() {
return "Student [name=" + name + ", addr=" + addr + "]";
}
public String getName() {
return name;
}
public String getAddr() {
return addr;
}
}
我有一个代码来创建地图,在其中存储学生姓名作为键,并存储一些处理过的addr值(一个List,因为我们为同一个学生提供了多个addr值)。
public class FilterId {
public static String getNum(String s) {
// should do some complex stuff, just for testing
return s.split(" ")[1];
}
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
list.add(new Student("a", "test 1", "type 1"));
list.add(new Student("a", "test 1", "type 2"));
list.add(new Student("b", "test 1", "type 1"));
list.add(new Student("c", "test 1", "type 1"));
list.add(new Student("b", "test 1", "type 1"));
list.add(new Student("a", "test 1", "type 1"));
list.add(new Student("c", "test 3", "type 2"));
list.add(new Student("a", "test 2", "type 1"));
list.add(new Student("b", "test 2", "type 1"));
list.add(new Student("a", "test 3", "type 3"));
list.add(new Student("a", "my test 4", "type 1"));
Map<String, List<String>> map = new HashMap<>();
}
}
我可以使用下面的代码来获得这样的输出。 {a=[1, 2, 3], b=[1, 2], c=[1, 3]}
Map<String, Set<String>> map = list.stream()
.collect(Collectors.groupingBy(
Student::getName,
Collectors.mapping(student -> getNum(student.getAddr()),
Collectors.toSet())));
但是我们如何为此增加额外的检查,
例如, if the type is type 3, then that entry should not go to the Set for that student
,
并向getNum
添加另一个约束检查,
public static String getNum(String s) {
// should do some complex stuff, just for testing
if(s.contains("my")) {
return "";
} else {
return s.split(" ")[1];
}
}
而且我不需要将该空字符串添加到与该Student关联的set
中。
因此,在这种情况下的预期输出将为{a=[1, 2], b=[1, 2], c=[1, 3]}
因为a
的test 3
是type 3
。 并且a
也是my test 4
因为它也未通过检查。
如何使用Java 8流实现此目标。
只需在开始分组之前插入filter()
调用即可(使用您选择的Predicate
):
Map<String, Set<String>> map = list.stream()
.filter(s -> !s.type.equals("type 3"))
.collect(Collectors.groupingBy(
Student::getName,
Collectors.mapping(student -> getNum(student.getAddr()), Collectors.toSet())));
结果: {a=[1, 2, test], b=[1, 2], c=[1, 3]}
这对所有要求都应该是好的,并且不需要getNum
方法:
Map< String, Set<String> > map = list.stream()
.filter( s -> !Objects.equals( s.getType(), "type 3") )
.filter( s -> !s.getAddr().contains("my") )
.collect( Collectors.groupingBy( Student::getName,
Collectors.mapping( s -> s.getAddr().split(" ")[1], Collectors.toSet() ) ) );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.