【问题标题】:Can I flatten multi depth self-referencing entities?我可以展平多深度自引用实体吗?
【发布时间】:2017-03-24 12:31:37
【问题描述】:

我有一个实体自引用。

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

【问题讨论】:

  • @talex 查看我的更新。
  • 这个函数不返回任何东西,它只是遍历所有元素。

标签: java list java-stream flatten self-reference


【解决方案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);

对于“main”方法,它应该可以在不崩溃的情况下工作。

希望这会有所帮助。

【讨论】:

    【解决方案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,所以我删除了它。还有一些流和返回的转换。

    【讨论】:

      【解决方案3】:

      如果您要使用基于 Stream 的解决方案,您可以创建以下方法

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-08
        • 1970-01-01
        • 2016-01-12
        • 1970-01-01
        • 1970-01-01
        • 2019-03-14
        相关资源
        最近更新 更多