我有一个实体自我引用。
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 :(得分: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 :(得分: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 :(得分: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());