我试着按genderdepartment分组a list of employees.

我如何确保所有departments人都包含在sorted order中,即使相关性别为count is zero

目前,我有以下代码和输出

employeeRepository.findAll().stream()
            .collect(Collectors.groupingBy(Employee::getGender, 
                        Collectors.groupingBy(Employee::getDepartment, 
                                              Collectors.counting())));

//output
//{MALE={HR=1, IT=1}, FEMALE={MGMT=1}}

Preferred output is:

{MALE={HR=1, IT=1, MGMT=0}, FEMALE={HR=0, IT=0, MGMT=1}}

推荐答案

要做到这一点,首先你必须按department分组,然后再按gender分组,而不是相反.

第一收集器groupingBy(Employee::getDepartment, _downstream_ )将基于部门将数据集分成组.在应用它时,它将根据员工性别将映射到每个部门的数据划分为two个部分.最后,作为下游应用的Collectors.counting()将为每department名员工提供gender名员工中的total number名.

因此,collect()操作产生的中间体map将是Map<String, Map<Boolean, Long>>-employee count×gender(Boolean)型,每department(for simplicity, department is a plain string)个.

下一步是将这张 map 转换为Map<Employee.Gender, Map<String, Long>>-employee countdepartment,每个gender.

我的方法是在条目集上创建一个流,并将each entry替换为一个新的条目集,该条目集将gender作为其key,为了保留关于department的信息,其value将依次是一个条目,department作为键,count by department作为其值.

然后用entry key收集stream of entriesgroupingBy.将mapping用作下游收集器,以提取nested entry.然后应用Collectors.toMap()Map.Entry<String, Long>类型的条目收集到 map 中.

所有departments个都包含在sorted订单中

为了确保嵌套映射(department by count)中的顺序,应使用NavigableMap.

为了做到这一点,需要使用预期为mapFactorytoMap()口味(it also expects a 102 which isn't really useful for this task since there will be no duplicates, but it has to be provided as well).

public static void main(String[] args) {
    List<Employee> employeeRepository = 
            List.of(new Employee("IT", Employee.Gender.MALE),
                    new Employee("HR", Employee.Gender.MALE),
                    new Employee("MGMT", Employee.Gender.FEMALE));

    Map<Employee.Gender, NavigableMap<String, Long>> departmentCountByGender = employeeRepository
            .stream()
            .collect(Collectors.groupingBy(Employee::getDepartment, // Map<String, Map<Boolean, Long>> - department to *employee count* by gender
                        Collectors.partitioningBy(employee -> employee.getGender() == Employee.Gender.MALE,
                                                  Collectors.counting())))
            .entrySet().stream()
            .flatMap(entryDep -> entryDep.getValue().entrySet().stream()
                    .map(entryGen -> Map.entry(entryGen.getKey() ? Employee.Gender.MALE : Employee.Gender.FEMALE,
                                               Map.entry(entryDep.getKey(), entryGen.getValue()))))
            .collect(Collectors.groupingBy(Map.Entry::getKey,
                        Collectors.mapping(Map.Entry::getValue,
                                Collectors.toMap(Map.Entry::getKey,
                                                 Map.Entry::getValue,
                                                 (v1, v2) -> v1,
                                                 TreeMap::new))));

    System.out.println(departmentCountByGender);
}

用于演示目的的Dummy Employee class:

class Employee {
    enum Gender {FEMALE, MALE};

    private String department;
    private Gender gender;
    // etc.
    
    // constructor, getters
}

Output

{FEMALE={HR=0, IT=0, MGMT=1}, MALE={HR=1, IT=1, MGMT=0}}

Java相关问答推荐

使用log 4j2格式的Hibernate 显示SQL日志(log)

找到允许的最大底片

Java自定义ThreadPool—暂停任务提交并取消当前排队任务

Java函数式编程中的双值单值映射

';com.itextpdf.ext.html.WebColors已弃用

使用Testcontainers与OpenLiberty Server进行集成测试会抛出SocketException

测试期间未执行开放重写方法

如何使用Jackson将XML元素与值和属性一起封装

如何从日期中截取时间并将其传递给组件?

当构造函数创建一个新实例时,Java为什么需要&new";

A.ForEach与For(类型a:集合)

为什么mvn编译生命周期阶段不只是编译已更改的java文件?

Java KeyListener不工作或被添加

无法使用Open WebStart Java 8运行jnlp

如何使用jOOQ在PostgreSQL中从枚举类型生成Java枚举

由于可为null,无法在kotlin中实现java接口

当我try 返回可选时,Mock无法正常工作

窗口启动后不久,从java.awt.Graphics disapear创建的矩形

更新不可变的深层嵌套字段

元音变音字符:如何在 Java 中将Á<0x9c>转换为Ü?