gpt4 book ai didi

java - 我可以使用 groupingBy 声明式地执行此操作吗?

转载 作者:行者123 更新时间:2023-12-02 02:19:29 24 4
gpt4 key购买 nike

我有一个Employee类:

public class Employee {

public enum Sex {
MALE, FEMALE
}

private final String name;
private final Sex gender;
private final LocalDate dateOfBirth;
private final double salary;
private final List<String> roles;

// Constructor
public Employee(String name, Sex gender, LocalDate dateOfBirth, double salary, List<String> roles) {
this.name = name;
this.gender = gender;
this.dateOfBirth = dateOfBirth;
this.salary = salary;
this.roles = roles;
}

// Getters & toString omitted

public static List<Employee> listOfStaff() {

List<Employee> staff = new ArrayList<>();
staff.add(new Employee("Jack", Employee.Sex.MALE,
IsoChronology.INSTANCE.date(1954, 12, 2), 49999.00,
new ArrayList<>(Arrays.asList("Manager", "Director"))));
staff.add(new Employee("Jill", Employee.Sex.FEMALE,
IsoChronology.INSTANCE.date(1995, 10, 25), 24999.00,
new ArrayList<>(Arrays.asList("Secretary", "Manager", "Personnel"))));
staff.add(new Employee("Dorothy", Employee.Sex.FEMALE,
IsoChronology.INSTANCE.date(1972, 4, 7), 21999.00,
new ArrayList<>(Arrays.asList("Secretary", "Receptionist"))));
staff.add(new Employee("Bert", Employee.Sex.MALE,
IsoChronology.INSTANCE.date(1968, 11, 5), 21999.00,
new ArrayList<>(Arrays.asList("Clerk", "Receptionist"))));
staff.add(new Employee("Mary", Employee.Sex.FEMALE,
IsoChronology.INSTANCE.date(2001, 12, 3), 16999.00,
new ArrayList<>(Arrays.asList("Trainee", "Receptionist"))));
staff.add(new Employee("Matthew", Employee.Sex.MALE,
IsoChronology.INSTANCE.date(1962, 4, 7), 12999.00,
new ArrayList<>(Arrays.asList("Personnel", "Receptionist"))));

return staff;
}
}

我可以迭代地提取角色和该角色中的人员:

public class TestGrouping {
/* Grouping streams */
public static void main(String[] args) {

Map<String, List<String>> roleAndNames = new HashMap<>();

for (Employee e : Employee.listOfStaff()) {
List<String> roles = e.getRoles();
List<String> names = new ArrayList<>();
names.add(e.getName());

for (String r : roles) {
if(roleAndNames.get(r) == null) {
roleAndNames.put(r, names);
} else {
roleAndNames.get(r).add(e.getName());
}
}
}
for (Map.Entry<String, List<String>> entry : roleAndNames.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue().toString());
}
}
}

这给了我以下输出:

enter image description here

我尝试使用流以声明方式执行相同的操作,但似乎无法获得相同的结果。

我以为我可以使用 groupingBy() 和collectingAndThen() 来做到这一点,但没有什么乐趣!

这可能吗?

最佳答案

以下是逐步解决的方法:

  1. 您可以使用flatMap获取所有可能的“角色名称”对 ( Map.Entry<String, String> )。
  2. 使用Collectors.groupingBy收集进入Map使用额外的Collectors.mapping结构下游收集器提取 name平面映射的“角色名称”对。它需要另一个将这些名称打包到 List 中。 .
Map<String, List<String>> map = Employee.listOfStaff().stream()
.flatMap(employee -> employee.getRoles()
.stream()
.map(role -> new AbstractMap.SimpleEntry<>(role, employee.getName())))
.collect(Collectors.groupingBy(
Entry::getKey,
Collectors.mapping(Entry::getValue, Collectors.toList())));

map.forEach((k,v) -> System.out.println(k + ":" + v));

我看到你使用 。如果您稍后切换到较新的 Java,则可以使用 Map.entry(..) 从 Java 9 开始,而不是 new AbstractMap.SimpleEntry(...) .


编辑:如果您不想使用 ,要修复当前的迭代代码,您需要修复 List插入/更新 map (两个片段的工作原理相同):

Map<String, List<String>> roleAndNames = new HashMap<>();
for (Employee employee: Employee.listOfStaff()) {
for (String role: employee.getRoles()) {
List<String> names = new ArrayList<>();
if (roleAndNames.containsKey(role)) {
names = roleAndNames.get(role);
}
names.add(employee.getName());
roleAndNames.put(role, names);
}
}
Map<String, List<String>> roleAndNames = new HashMap<>();
for (Employee employee: Employee.listOfStaff()) {
for (String role: employee.getRoles()) {
List<String> names = roleAndNames.getOrDefault(role, new ArrayList<>());
names.add(employee.getName());
roleAndNames.put(role, names);
}
}

...或者更好地使用 Map#computeIfAbsent 如果没有任何条目,它会创建一个新条目,并且始终返回该值(这是一个列表,可以是空列表,也可以是带有一些名称的列表)。因此,您总是使用它在每次迭代中添加名称。

Map<String, List<String>> roleAndNames = new HashMap<>();
for (Employee employee: Employee.listOfStaff()) {
for (String role: employee.getRoles()) {
roleAndNames.computeIfAbsent(role, roleKey -> new ArrayList<>())
.add(employee.getName());
}
}

仅此而已:)我喜欢这个方法及其返回类型。非常方便!

关于java - 我可以使用 groupingBy 声明式地执行此操作吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66641233/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com