展平通用 Java 树
我有一个可以有父母和孩子的模型接口
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,似乎存在一个概念问题:
对某些基类的 HierarchyAware 会阻止在编译时生成派生类的子级 (getChildren)。因此,安全地获取派生类的 List 始终是不安全的。
也就是说,如果您的意思不是 A 类只有 A 类的子级,依此类推。那是可行的。
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.