开发者

Flattening a generic Java tree

开发者 https://www.devze.com 2023-04-11 17:52 出处:网络
I have an interface for models that can have parents and children public interface HierarchyAware<T extends HierarchyAware<T>> {

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?


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;
0

精彩评论

暂无评论...
验证码 换一张
取 消