2016-11-10 34 views
0

我有一個實體自引用。我可以拼合多個深度自引用實體嗎?

public class Category { 

    private List<Category> children; 
} 

隨着給定的類別列表,我該如何將它們全部弄平?

C11 
    C21 
     C31 
     C32 
    C22 
C12 

我想要的

C1 C21 C31 C32 C22 C12 

我嘗試了名單。

public static <T extends BaseEntity & SelfReferencing<T>> void flatten(
     final T parent, final Function<T, Stream<T>> function, 
     final Consumer<T> consumer) { 
    function.apply(parent).forEach(child -> { 
     consumer.accept(child); 
     flatten(child, function, consumer); 
    }); 
} 
+0

@talex查看我的更新。 –

+0

該函數不會返回任何只是遍歷所有元素的任何東西。 – talex

回答

1

您是否在尋找像下面?的「扁平化」一個遞歸函數...

import java.util.ArrayList; 
import java.util.List; 

public class Flatten { 

    static class Category { 
     private List<Category> children; 
     private String name; 

     public Category(String name) { 
      this.name = name; 
     } 

     public List<Category> getChildren() { 
      if(children == null) { 
       children = new ArrayList<>(); 
      } 
      return children; 
     } 

     public void setChildren(List<Category> children) { 
      this.children = children; 
     } 

     @Override 
     public String toString() { 
      return name; 
     } 
    } 

    public static void main(String[] args) { 
     Category root = new Category("ROOT"); 
     Category c11 = new Category("C11"); 
     Category c12 = new Category("C12"); 
     Category c21 = new Category("C21"); 
     Category c22 = new Category("C22"); 
     Category c31 = new Category("C31"); 
     Category c32 = new Category("C32"); 

     root.getChildren().add(c11); 
     root.getChildren().add(c12); 
     c11.getChildren().add(c21); 
     c11.getChildren().add(c22); 
     c21.getChildren().add(c31); 
     c21.getChildren().add(c32); 

     List<Category> flat = flatten(root.getChildren()); 

     System.out.println(flat); 
    } 

    private static List<Category> flatten(List<Category> c) { 
     List<Category> flatList = new ArrayList<>(); 

     flatten(flatList, c); 

     return flatList; 
    } 

    private static void flatten(List<Category> flatList, List<Category> c) { 
     for (Category category : c) { 
      flatList.add(category); 
      flatten(flatList, category.getChildren()); 
     } 
    } 
} 

如果有「循環」,在您的層次結構,(例如,C31具有C11作爲一個孩子),你可以添加以下做,直到你耗盡內存確保事情不會永遠循環......

private static void flatten(List<Category> flatList, List<Category> c) { 
    for (Category category : c) { 
     if(!flatList.contains(category)) { 
      flatList.add(category); 
      flatten(flatList, category.getChildren()); 
     } 
    } 
} 

現在,如果你添加...

c21.getChildren().add(c11); 

對於「主」方法,它應該工作而不會爆炸。

希望這會有所幫助。

2

我把你的代碼改進了一下。

public static <T extends BaseEntity & SelfReferencing<T>> List<T> flatten(
     final T parent, final Function<T, Stream<T>> function) { 
    List<T> res = new ArrayList<>(); 
    res.add(parent); 
    res.addAll(function.apply(parent).flatMap(child -> { 
     flatten(child, function).stream(); 
    }).collect(Collectors.toList())); 
    return result; 
} 

我不明白你爲什麼需要consumer我刪除它。還有一些轉換爲流式轉換。

1

如果你正往一個基於流的解決方案,您可以創建以下方法

public static <T> Stream<T> flatten(T node, Function<T,Stream<T>> children) { 
    return Stream.concat(Stream.of(node), 
     children.apply(node).flatMap(ch->flatten(ch, children))); 
} 

,並重新實現你喜歡的方法「對每個執行的操作」

public static <T> void flatten(
    T parent, Function<T, Stream<T>> function, Consumer<T> consumer) { 

    flatten(parent, function).forEach(consumer); 
} 

但既然你說了,你想要一個List,你也可以用流式方法如

public static <T> List<T> toFlatList(T parent, Function<T, Stream<T>> function) { 
    return flatten(parent, function).collect(Collectors.toList()); 
} 

可與您的Category一起使用,如

List<Category> list=toFlatList(category, c -> c.getChildren().stream()); 
相關問題