繁体   English   中英

转换列表时过滤出值 <SomeObject> 到地图 <String, Set<String> &gt;使用Java 8流API

[英]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]}因为atest 3type 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM