2015-07-14 17 views
6

Hãy xem xét một lớp trong javaTìm hệ thống phân cấp

class Entity { 

Integer id; 
Integer parentId; 

public Integer getId() { 
    return id; 
} 

public void setId(Integer id) { 
    this.id = id; 
} 

public Integer getParentId() { 
    return parentId; 
} 

public void setParentId(Integer parentId) { 
    this.parentId = parentId; 
} 


} 
} 

Cân nhắc ParentID như chìa khóa nước ngoài (liên quan đến id để đối tượng khác).

Bây giờ tôi đã tạo 6 đối tượng và đặt một số giá trị.

Entity e1 = new Entity(); 
    e1.setId(400); 

    Entity e2 = new Entity(); 
    e2.setId(300); 
      e2.setParentId(400); 

    Entity e3 = new Entity(); 
    e3.setId(200); 
    e3.setParentId(300); 

    Entity e4 = new Entity(); 
    e4.setId(100); 
      e4.setParentId(200); 

    Entity e5 = new Entity(); 
    e5.setId(50); 
      e5.setParentId(100); 

    Entity e6 = new Entity(); 
    e6.setParentId(50); 

Bây giờ tôi muốn nhận được thứ bậc của các đối tượng. Điều đó có nghĩa là nếu tôi cung cấp id, tôi sẽ nhận được hệ thống cấp bậc cha và phân cấp con hoàn chỉnh.

cho ví dụ: nếu tôi cung cấp cho 100 như id (đơn vị: e4), tôi sẽ nhận được phân cấp cha con: - e4, e3, e2, e1 hệ thống phân cấp con: - e4, e5, e6

Giải thích: - đối với phân cấp cha: - chúng ta nên thêm đối tượng e4 ban đầu trước tiên. sau đó chúng ta sẽ tìm thấy đối tượng có iD giống như của parent4d của e4 (ở đây e3) quá trình tiếp tục cho đến khi parentid rỗng là cho hệ phân cấp con: - chúng ta nên thêm đối tượng e4 ban đầu trước. sau đó chúng ta sẽ tìm thấy đối tượng có parentId giống với id của e4. (Ở đây e5) quá trình này tiếp tục cho đến khi, các ParentID là null

Giải pháp của tôi cho hệ thống cấp bậc cha mẹ: -

List<Entity> parent = new ArrayList<Entity>(); 

    Entity ent = list.stream().filter(e -> e.getId() == 100).findFirst() 
      .get(); // // 100 input id value 

    parent.add(ent); 

    Integer parentId = ent.getParentId(); 

    while (parentId != null) { 

     int search = parentId; 
     Entity newEntity = list.stream().filter(e -> e.getId() == search) 
       .findFirst().get(); 

     parent.add(newEntity); 
     parentId = newEntity.getParentId(); 
    } 

cho hệ thống phân cấp con:

Entity entnew = list.stream().filter(e -> e.getId() == 100).findFirst() 
      .get(); // 100 input id value 



    child.add(entnew); 


    Integer idNew = entnew.getId(); 


    while (idNew != null) { 

    int searchNew = idNew; 

    Entity newEnt = list.stream().filter(f -> f.getParentId()!= null && f.getParentId() == searchNew) 
      .findFirst().get(); 

    child.add(newEnt); 
    idNew = newEnt.getId(); 

    } 

tôi thấy phương pháp này để giải quyết kịch bản, Nhưng tôi muốn có một giải pháp hiệu quả hơn trong java 8 bằng cách sử dụng các khái niệm cốt lõi của nó để giải quyết vấn đề này.

+0

là bất kỳ lý do nào tại sao bạn giữ 'parentId' thay vì tham chiếu đến cha mẹ? – user902383

Trả lời

1

Tôi đã tìm thấy giải pháp Java8-ish hơn, có mùi lập trình hàm.

Với sáu thực thể của bạn (xin lưu ý rằng tôi đã thiết lập các Id cho e6, nếu không chúng tôi có được một NullPointerException):

Entity e1 = new Entity(); 
e1.setId(400); 

Entity e2 = new Entity(); 
e2.setId(300); 
e2.setParentId(400); 

Entity e3 = new Entity(); 
e3.setId(200); 
e3.setParentId(300); 

Entity e4 = new Entity(); 
e4.setId(100); 
e4.setParentId(200); 

Entity e5 = new Entity(); 
e5.setId(50); 
e5.setParentId(100); 

Entity e6 = new Entity(); 
e6.setId(25); // this Id must be set, or we'll get a NPE 
e6.setParentId(50); 

Và một danh sách có chứa chúng:

List<Entity> list = new ArrayList<>(); 
list.add(e1); 
list.add(e2); 
list.add(e3); 
list.add(e4); 
list.add(e5); 
list.add(e6); 

Sau đó, cho hệ thống phân cấp của cha mẹ:

Function<Integer, Entity> byId = 
    id -> list.stream() 
     .filter(e -> e.getId().equals(id)) 
     .findFirst() 
     .orElse(null); 

Entity parentsSeed = byId.apply(100); // e4 

UnaryOperator<Entity> nextParent = 
    e -> e == null ? e : byId.apply(e.getParentId()); 

List<Entity> parents = 
    Stream.iterate(parentsSeed, nextParent) 
     .limit(list.size()) 
     .filter(Objects::nonNull) 
     .collect(Collectors.toList()); // [e4, e3, e2, e1] 

Và đối với phân cấp của trẻ em:

Entity childrenSeed = byId.apply(100); // e4 

Function<Integer, Entity> byParentId = 
    id -> list.stream() 
     .filter(e -> id.equals(e.getParentId())) 
     .findFirst() 
     .orElse(null); 

UnaryOperator<Entity> nextChild = 
    e -> e == null ? e : byParentId.apply(e.getId()); 

List<Entity> children = 
    Stream.iterate(childrenSeed, nextChild) 
     .limit(list.size()) 
     .filter(Objects::nonNull) 
     .collect(Collectors.toList()); // [e4, e5, e6] 

Ý tưởng là sử dụng phương pháp Stream.iterate(), bằng cách tạo luồng bằng cách lặp lại "chức năng".

Đối với cha mẹ, tôi đã tạo một UnaryOperator (một chức năng) được cho là Entity, trả về số gốc là Entity hoặc null; đối với trẻ em, tôi đã tạo một UnaryOperator, với số Entity, trả về con của nó là Entity hoặc null.

Để thực hiện hai tìm kiếm đó, tôi đã sử dụng một số khác Function chỉ cần tìm kiếm lần lượt list theo số idparentId.

-1

Bạn có phải sử dụng id int để liên kết với phụ huynh không? Tùy thuộc vào những gì bạn đang cố gắng đạt được, nhưng bạn không thể chỉ liên kết như thế:

class Entity { 
    Integer id; 
    Entity parent; 
} 

Sau đó, bạn sẽ không phải tìm kiếm toàn bộ danh sách khi bạn có thực thể đầu tiên của mình.

+0

Tôi nghĩ bạn nên cung cấp giải pháp cho câu hỏi này, không phải bằng cách chỉnh sửa câu hỏi –

+0

Sử dụng cấu trúc dữ liệu thích hợp cho một số vấn đề ít nhất cũng quan trọng như chính thuật toán. Nếu bạn sử dụng cấu trúc dữ liệu không phù hợp với vấn đề, thuật toán có thể chậm và phức tạp. Vì vậy tôi hỏi nếu có bất kỳ lý do nào tại sao phải sử dụng cấu trúc dữ liệu này. – user140547

0

tôi sẽ tạo ra bảng tra cứu cho các đối tượng, phụ huynh và trẻ em:

List<Integer> ancestors = new ArrayList<>(); 
List<Integer> descendants = new ArrayList<>(); 
Map<Integer, Entity> objectById = list.stream().collect(Collectors.toMap(e ->e.getId(), e->e)); 
Map<Integer, Integer> parentIdByChildId = list.stream().collect(Collectors.toMap(e->e.getId(), e ->e.getParentId()); 
Map<Integer, Integer> childIdByParentId = list.stream().collect(Collectors.toMap(e ->e.getParentId(), e->e.getId()); 
Integer parentId = 10; 
Integer current = parentId; 
while(current!=null) { 
    current = childIdByParentId.get(current); 
    if(current!=null){ 
     descendants.add(objectById.get(current)); 
    } 
} 
current = parentId; 
while(current!=null) { 
    current = parentIdByChildId.get(current); 
    if(current!=null){ 
     ancestors.add(objectById.get(current)); 
    } 
} 

này không hỗ trợ các thực thể với nhiều trẻ em, bạn có thể muốn kiểm tra ví dụ cho java.util.stream.Collectors.groupBy

Các vấn đề liên quan