Java递归父子层次结构

时间:2021-04-08 11:10:13

标签: java java-8

class Employee{
  private String employeeId;
  private boolean isLeaf;
  private List<Employee> children;    
}

empl
   emp2
     emp2a
     emp2b
       emp2b1

   emp3
     emp3a
..
..
..

通过上面的层次结构,我想为每个员工创建孩子。

预期输出:获取每个父级的子级

Map<String,Set<String>>

{"empl1",["emp2","emp2a","emp2b","emp2b1","emp3","emp3a"]}

{"empl2",["emp2a","emp2b","emp2b1"]}

{"empl2b",["emp2b1"]}

{"emp3",["emp3a"]}

这是否可以使用现有的 Employee 类结构?

试过这个,虽然不起作用,不知道如何/在哪里停止循环 任何帮助都受到高度赞赏。谢谢!

public void visitAllNodes(Employee emp){
   Map<String,Set> childMap = new HashMap<>();
       Map<String,Set> finalResult = 
   visitChildNodesTest(childMap,emp.getEmployeeId(),emp.getEmployees());
      
   }



private Map<String, List> visitChildNodesTest(Map<String, List> 
   parentChildMap, String parentEmpId,
    List<Employee> employees) {
    if (CollectionUtils.isNotEmpty(employees)) {
    employees.forEach(employee -> {
      if (employee.getEmployees() != null) {
        getAndPut(parentChildMap,employee.getEmployeeId(),parentEmpId);
        visitChildNodesTest(parentChildMap, employee.getEmployeeId(), 
       employee.getEmployees());
      }
    });
  
  }
  return parentChildMap;
}

  private void getAndPut(Map<String, List> parentChildMap, String 
   employeeId, String parentEmpId) {
  if (parentChildMap.get(parentEmpId) == null) {
     List<String> ls = new ArrayList<>();
       ls.add(parentEmpId);
        ls.add(employeeId);
      parentChildMap.put(parentEmpId, ls);
    }  else {
      List ls = parentChildMap.get(parentEmpId);
        ls.add(employeeId);
        parentChildMap.put(parentEmpId, ls);
    }
  
 }

4 个答案:

答案 0 :(得分:1)

我认为解决方案的基础是这样的递归方法:

public Set<String> getDescendantIds() {  
    Set<String> result = new HashSet<>();
    if (!isLeaf) {
        children.forEach(c -> result.add(c.employeeId));
        children.forEach(c -> result.addAll(c.getDescendantIds()));
    }
    return result;
}

答案 1 :(得分:1)

试试这个。

class Employee {
    private String employeeId;
    public String getEmployeeId() { return employeeId; }
    private boolean isLeaf() { return children.size() == 0; }
    private List<Employee> children = new ArrayList<>();
    @Override public String toString() { return employeeId; }

    public Employee(String employeeId, Employee... children) {
        this.employeeId = employeeId;
        for (Employee child : children)
            this.children.add(child);
    }

    public Set<Employee> descendants() {
        Set<Employee> descendants = new LinkedHashSet<>();
        for (Employee child : children) {
            descendants.add(child);
            descendants.addAll(child.descendants());
        }
        return descendants;
    }
}

Employee emp1 =
    new Employee("emp1",
        new Employee("emp2",
            new Employee("emp2a"),
            new Employee("emp2b",
                new Employee("emp2b1"))),
        new Employee("emp3",
            new Employee("emp3a")));

Set<Employee> employees = new LinkedHashSet<>();
employees.add(emp1);
employees.addAll(emp1.descendants());
System.out.println(employees);

Map<String, Set<String>> map = employees.stream()
    .filter(Predicate.not(Employee::isLeaf))
    .collect(Collectors.toMap(Employee::getEmployeeId,
        e -> e.descendants()
            .stream()
            .map(Employee::getEmployeeId)
            .collect(Collectors.toSet())));
System.out.println(map);

输出

[emp1, emp2, emp2a, emp2b, emp2b1, emp3, emp3a]
{emp3=[emp3a], emp2=[emp2b1, emp2a, emp2b], emp1=[emp2b1, emp3, emp3a, emp2, emp2a, emp2b], emp2b=[emp2b1]}

答案 2 :(得分:1)

Employee 类中的这样的函数应该可以做到这一点。

public Set<Employee> deepList(){
    Set<Employee> result = new HashSet<>();
    for(Employee e : children){
        result.add(e);
        for(Employee c : e.deepList()) result.add(c);
    }
    return result;
}

这是一个简短的测试:

import java.util.*;

class Employee{
    public static void main(String[] args) {
        // only for testing
        Employee emp1  = new Employee("emp1");
        Employee emp2  = emp1.addChildren(new Employee("emp2"));
                         emp2.addChildren(new Employee("emp2a"));
        Employee emp2b = emp2.addChildren(new Employee("emp2b"));
                         emp2b.addChildren(new Employee("emp2b1"));
        Employee emp3  = emp1.addChildren(new Employee("emp3"));
                         emp3.addChildren(new Employee("emp3a"));

        emp1.deepListTest();
    }

    private String employeeId;
    private boolean isLeaf;
    private List<Employee> children = new ArrayList<>();

    public Employee(String employeeId) {
        this.employeeId = employeeId;
    }

    public Employee addChildren(Employee employee){
        children.add(employee);
        return employee;
    }

    public String getEmployeeId() {
        return employeeId;
    }

    // only for test purposes as a set<String>
    public Set<String> deepListTest(){
        Set<String> result = new HashSet<>();
        for(Employee e : children){
            result.add(e.getEmployeeId());
            for(String c : e.deepListTest()) result.add(c);
        }
        if(!children.isEmpty()) System.out.println("{" + employeeId + ", [" + String.join(", ", result) + "]}");
        return result;
    }
}

结果:

{emp2b, [emp2b1]}
{emp2, [emp2b1, emp2a, emp2b]}
{emp3, [emp3a]}
{emp1, [emp2b1, emp3, emp3a, emp2, emp2a, emp2b]}

希望这能解决您的问题。

答案 3 :(得分:0)

我觉得你的代码看起来不错,除了只需要删除最后一行“parentChildMap.put(parentEmpId, ls);”,然后代码会按你的预期工作,当它通过所有节点时它会自动停止,因为你有那里的“isNotEmpty”条件。

有关为什么需要删除该行的更多信息,因为 List ls = parentChildMap.get(parentEmpId); 已经获得了列表引用,您只需将该元素添加到该列表中