2016-11-10 35 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()); 
相关问题