展平通用 Java 树

发布于 2024-12-08 14:12:07 字数 1848 浏览 0 评论 0原文

我有一个可以有父母和孩子的模型接口

public interface HierarchyAware<T extends HierarchyAware<T>> {

  List<T> getChildren();

  T getParent();

  void addChild(T child);

}

我有一个实用方法,它采用平面列表并构建一棵树:

<T extends HierarchyAware<? super T>> List<T> buildTree(List<T> flatElements);

它工作正常,因此无需发布方法主体。

我还有一种方法可以将树展平为简单的列表:

  public static List<? extends HierarchyAware<?>> flattenTree(List<? extends HierarchyAware<?>> treeElements) {
    List<HierarchyAware<?>> flatList = new ArrayList<HierarchyAware<?>>();
    for (HierarchyAware<?> t : treeElements) {
      flatList.add(t);
      if (t.getChildren() != null) {
        flatList.addAll(flattenTree(t.getChildren()));
      }
    }
    return flatList;
  }

但我真的不喜欢它的签名并希望使其更具体。所以我这样编码:

  @SuppressWarnings("unchecked")
  public static <T extends HierarchyAware<? super T>> List<T> flattenTree(List<T> treeElements) {
    List<T> flatList = new ArrayList<T>();
    for (T t : treeElements) {
      flatList.add(t);
      if (t.getChildren() != null) {
        flatList.addAll((List<? extends T>) flattenTree(t.getChildren()));
      }
    }
    return flatList;
  }

签名对我来说是完美的,但我不喜欢抑制警告的需要。最大的问题是 Eclipse 编译器发现这段代码是合法的,但是 javac 给了我:

[javac] C:\somepath\TreeUtil.java:112: <T>flattenTree(java.util.List<T>) in somepackage.TreeUtil cannot be applied to (java.util.List<capture#687 of ? super T>)
[javac]         flatList.addAll((List<? extends T>) flattenTree(t.getChildren()));
[javac]                                             ^

为什么两个编译器的行为不同,我应该如何重写这个方法,这样它就会出错,并且最好没有警告?

I have an interface for models that can have parents and children

public interface HierarchyAware<T extends HierarchyAware<T>> {

  List<T> getChildren();

  T getParent();

  void addChild(T child);

}

I have a utility method that takes a flat list and builds a tree:

<T extends HierarchyAware<? super T>> List<T> buildTree(List<T> flatElements);

It works fine, so there's no need to post the method body.

I also have a method that flattens a tree into a plain list:

  public static List<? extends HierarchyAware<?>> flattenTree(List<? extends HierarchyAware<?>> treeElements) {
    List<HierarchyAware<?>> flatList = new ArrayList<HierarchyAware<?>>();
    for (HierarchyAware<?> t : treeElements) {
      flatList.add(t);
      if (t.getChildren() != null) {
        flatList.addAll(flattenTree(t.getChildren()));
      }
    }
    return flatList;
  }

but I really don't like it's signature and want to make it more specific. So I've coded it like this:

  @SuppressWarnings("unchecked")
  public static <T extends HierarchyAware<? super T>> List<T> flattenTree(List<T> treeElements) {
    List<T> flatList = new ArrayList<T>();
    for (T t : treeElements) {
      flatList.add(t);
      if (t.getChildren() != null) {
        flatList.addAll((List<? extends T>) flattenTree(t.getChildren()));
      }
    }
    return flatList;
  }

Signature is perfect for me, but I don't like the need to suppress warnings. And the biggest problem is that Eclipse compiler finds this code legit, but javac gives me:

[javac] C:\somepath\TreeUtil.java:112: <T>flattenTree(java.util.List<T>) in somepackage.TreeUtil cannot be applied to (java.util.List<capture#687 of ? super T>)
[javac]         flatList.addAll((List<? extends T>) flattenTree(t.getChildren()));
[javac]                                             ^

Why are two compilers behaving differently and how should I rewrite this method so it would be error and ideally warning-free?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遗弃M 2024-12-15 14:12:08

首先,似乎存在一个概念问题:

对某些基类的 HierarchyAware 会阻止在编译时生成派生类的子级 (getChildren)。因此,安全地获取派生类的 List 始终是不安全的。

也就是说,如果您的意思不是 A 类只有 A 类的子级,依此类推。那是可行的。

    public static <T extends HierarchyAware<T>> List<T> flattenTreeX(List<T> treeElements) {
    List<T> flatList = new ArrayList<T>();
    for (T t : treeElements) {
        flatList.add(t);
        if (t.getChildren() != null) {
            flatList.addAll((List<? extends T>) flattenTreeX(t.getChildren()));
        }
    }
    return flatList;

Before all there seems to be a conceptual problem:

Being HierarchyAware of some base class prevents yielding children of derived classes at compile time (getChildren). So safely getting a List of a derived class is always unsafe.

That is if you do not mean that class A only has Children of class A and so on. That would be doable.

    public static <T extends HierarchyAware<T>> List<T> flattenTreeX(List<T> treeElements) {
    List<T> flatList = new ArrayList<T>();
    for (T t : treeElements) {
        flatList.add(t);
        if (t.getChildren() != null) {
            flatList.addAll((List<? extends T>) flattenTreeX(t.getChildren()));
        }
    }
    return flatList;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文