首页 文章

Java 8 Collectors API

提问于
浏览 265 次
7

这个问题涉及使用java 8收集器对元素进行映射和分组 . 我有一份患者名单 . 每位患者都有他访问过的部门列表 . 假设我想为每个部门计算在Java 8中使用新的收集器API访问了多少时间,我将如何按部门列表进行分组?

谢谢!

NOTE: 我知道我可以在每个部门都设置一个计数器,这个问题仅仅是为了学习新的java 8功能 .

码:

public class Patient {
    private String id;
    private List<Department> history;
    /* some more getters/setters come here */
}

在我的主要方法中,我有一份患者名单 . 我想知道每个部门,访问了多少时间,没有编辑部门类(或扩展或装饰它) .

我想我必须接受一批患者并将他们映射到dept-> count的 Map (每位患者访问哪个部门的次数) . 拥有这些 Map 的流 - 我不知道如何分组这些 Map 并计算它们 .

1 回答

  • 11

    首先,我假设如果患者不止一次访问过某个部门,该部门将不止一次出现在患者的病史列表中 .

    如果是这种情况,那么我们可以简单地将我们的患者流和 flatMap 它带到一个部门流,其中部门的出现表明来自患者的一次访问 .

    然后我们可以将它传递给 groupingBy 收集器 . 我们想按部门本身进行分类,因此分类器函数是身份函数 .

    对于值,我们想要将1作为值,如果Department的条目是't present yet, but we want to add 1 to the existing value if an entry is present. There'是一个名为 counting() 的收集器,它已经为我们做了这个,所以我们只将它作为下游收集器传递给 groupingBy() .

    结果代码如下:

    import static java.util.stream.Collectors.*;
    
    List<Patient> patients = ... ;
    
    Map<Department, Long> frequency =
        patients.stream()
            .flatMap(p -> p.getHistory().stream())
            .collect(groupingBy(d -> d, counting()));
    

    请注意,如果未访问某个部门,则只会在 Map 中缺少该部门 . 如果您有部门列表,则可以填写零值,如下所示:

    departments.forEach(d -> frequency.putIfAbsent(d, 0L));
    

    或者如果你想在 get 上填写零,

    long numVisits = frequency.getOrDefault(dept, 0L);
    

相关问题