[英]Filter out values when converting List<SomeObject> to Map<String, Set<String>> using Java 8 streams API
This problem is related to This SO question 这个问题涉及到这个问题的SO
I have an instances of Student class. 我有一个学生班的实例。
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;
}
}
And I have a code to create a map , where it store the student name as the key and some processed addr values (a List since we have multiple addr values for the same student) as the value. 我有一个代码来创建地图,在其中存储学生姓名作为键,并存储一些处理过的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<>();
}
}
I can have a code like below to get an out put like this. 我可以使用下面的代码来获得这样的输出。
{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())));
But how can we add an extra checks to this, 但是我们如何为此增加额外的检查,
like, if the type is type 3, then that entry should not go to the Set for that student
, 例如,
if the type is type 3, then that entry should not go to the Set for that student
,
And add another constraint check to getNum
like, 并向
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];
}
}
And I don't need to add that empty string to the set
associated with that Student. 而且我不需要将该空字符串添加到与该Student关联的
set
中。
So the expected output for that case will be, {a=[1, 2], b=[1, 2], c=[1, 3]}
Since a
's test 3
is type 3
one. 因此,在这种情况下的预期输出将为
{a=[1, 2], b=[1, 2], c=[1, 3]}
因为a
的test 3
是type 3
。 And the a
's my test 4
is also not considered since it fails the check as well. 并且
a
也是my test 4
因为它也未通过检查。
How can I achive this target with Java 8 streams. 如何使用Java 8流实现此目标。
Simply insert the filter()
call before starting the grouping (with the Predicate
of your choice): 只需在开始分组之前插入
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())));
Result: {a=[1, 2, test], b=[1, 2], c=[1, 3]}
结果:
{a=[1, 2, test], b=[1, 2], c=[1, 3]}
This should be good for all of requirements and no need to have getNum
method: 这对所有要求都应该是好的,并且不需要
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.