使用流查找 Employee 及其 Parent 的值总和

Find the sum of values of an Employee and its Parent using stream

考虑一下,我有以下 class.

public class Employee {

private Integer id;
private Integer parentId;
private int value;
}

现在我有以下记录。

    Employee employee1 = new Employee(1, null, 4);
    Employee employee2 = new Employee(2, 1, 4);
    Employee employee3 = new Employee(3, null, 8);
    Employee employee4 = new Employee(4, 1, 3);
    Employee employee5 = new Employee(5, 2, 11);

所以 parentId 员工 id,他是另一个 员工 的老板。

问题是找出 employee 的价值的 sum 和它是父级(如果有的话),或者 return 原样的值。所以在这种情况下,结果应该是。

id value
1 4
2 8
3 8
4 7
5 15

如何使用 java 8 个流实现此目的?我尝试了以下方法;

  Optional<Integer> first = employees.stream().map(a -> {
                int sum = 0;
                employees.stream().map(b -> {
                    if (Objects.equals(a.id, b.parentId)) {
                        sum = sum + a.value + b.value;
                    }else{
                        sum  = sum + a.value;
                    }
                    return sum;
                });
                return sum;
            }
    ).findFirst();

但是我在 sum 变量上遇到错误,它应该是最终的或实际上是最终的。

通过仅计算子项及其第一个父项的值,您可以使用列表中的简单过滤器来完成。

@Test
public void test() {
    final Employee employee1 = new Employee(1, null, 4);
    final Employee employee2 = new Employee(2, 1, 4);
    final Employee employee3 = new Employee(3, null, 8);
    final Employee employee4 = new Employee(4, 1, 3);
    final Employee employee5 = new Employee(5, 2, 11);

    final List<Employee> employees = List.of(employee1, employee2, employee3, employee4, employee5);
    final List<Pair<Integer, Integer>> res = employees
            .stream()
            .map(emp -> Pair.of(emp.id,
                            emp.value + employees
                                    .stream()
                                    .filter(e -> e.id.intValue() == Optional.ofNullable(emp.parentId).orElse(-1))
                                    .findFirst().map(Employee::getValue)
                                    .orElse(0)
                    )
            )
            .collect(Collectors.toList());
    res.forEach(System.out::println);
}

public class Employee {
    public Integer id;
    public Integer parentId;
    public int value;
    public Employee(final Integer id, final Integer parentId, final int value) {
        this.id = id;
        this.parentId = parentId;
        this.value = value;
    }
    public int getValue() {
        return this.value;
    }
}

结果:

(1,4)
(2,8)
(3,8)
(4,7)
(5,15)

注意:我使用的对象 Pair 来自 org.apache.commons.lang3.tuple.Pair

实现这一点的最有效方法是创建一个 map,它将允许检索 value Employee 由其 id.

然后,为了将每个 Employeevalue 与其父级的 value 相结合,使用 38=]map0 如果 parentnull.

下面的方法生成一个 map,其中 id 用作 key,员工的 value 作为 .

public static Map<Integer, Integer> getEmplValueById(List<Employee> employees) {
    return employees.stream()
            .collect(Collectors.toMap(Employee::getId,
                                      Employee::getValue));
}

以下方法创建了一个 map,其中 id 用作 key 并且 员工的总价值作为地图的价值

public static Map<Integer, Integer> getEmplSumById(List<Employee> employees,
                                                   Map<Integer, Integer> valueById) {
    return employees.stream()
            .collect(Collectors.toMap(Employee::getId,
                        empl -> empl.getValue() + 
                                valueById.getOrDefault(empl.getParentId(), 0)));
}

main()

public static void main(String[] args) {
    List<Employee> employees = List.of(
            new Employee(1, null, 4),
            new Employee(2, 1, 4),
            new Employee(3, null, 8),
            new Employee(4, 1, 3),
            new Employee(5, 2, 11));

    Map<Integer, Integer> valueById = getEmplValueById(employees);

    getEmplSumById(employees, valueById)
         .forEach((k, v) -> System.out.printf("ID %d \t value %d\n", k, v));
}

输出

ID 1     value 4
ID 2     value 8
ID 3     value 8
ID 4     value 7
ID 5     value 15