簡體   English   中英

Java 遞歸父子層次結構

[英]Java recursive parent child hierarchy

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

empl
   emp2
     emp2a
     emp2b
       emp2b1

   emp3
     emp3a
..
..
..

使用上述層次結構,我想創建每個員工的孩子。

預期output:獲取每個父母的孩子

Map<String,Set<String>>

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

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

{"empl2b",["emp2b1"]}

{"emp3",["emp3a"]}

這是否可以使用現有的 Employee class 結構?

試過這個,但不起作用,不知道如何/在哪里停止循環任何幫助都非常感謝。 謝謝!

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);
    }
  
 }

我認為解決方案的基礎是這樣的遞歸方法:

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;
}

嘗試這個。

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);

output

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

function 在您的員工 class 中應該這樣做。

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]}

我希望這能解決你的問題。

我認為您的代碼看起來不錯,除了只需要刪除“ parentChildMap.put(parentEmpId, ls); ”的最后一行,然后代碼將按您的預期工作,當它通過所有節點時它會自動停止,因為您那里有“isNotEmpty”的條件。

有關為什么需要刪除該行的更多信息,因為List ls = parentChildMap.get(parentEmpId); 已經獲得列表引用,您只需將元素添加到該列表

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM