使用泛型List作为varargs参数



我正在尝试实现一个通用树。

每个树都有一个value、一个parent和一个其children的列表。使用以下方法添加子项:

public Tree<T> addChildren(Tree<T>... children) {
    for (Tree<T> child: children) {
        if (this.children.add(child)) {
            child.setParent(this);
        }
    }
    return this;
}

当我有一个List树,我想作为孩子添加时,问题就开始了:

List<Tree<T>> newChildren;

由于在Java中无法创建参数化类型的数组,因此最明显的解决方案是迭代列表并逐个添加子项:

for (Tree<T> newChild: newChildren) {
   myTree.addChildren(newChild);
}

但这并不是对varargs的有效使用。既然我想让Tree类尽可能简单,有其他方法可以实现吗?

对于一个同时接受arrayList(或者更好的Iterable)的方法,我最喜欢的方法是使用数组版本中的Arrays.asList()来调用可迭代版本。示例:

public Tree<T> addChildren(Iterable<Tree<T>> children) { //for lists and collections
    // same code
}
public Tree<T> addChildren(Tree<T>... children) { //for arrays and varargs
    return addAll(Arrays.asList(children));
}

也不要害怕使用一些通配符,如果你想让Tree<Animal>小时候有一个Tree<Cat>,那么你需要把你的信号改为:

Tree<T> addAll(Iterable<? extends Tree<? extends T>> children) { ... }
Tree<T> addAll(Tree<? extends T>... children) { ... }

这可以通过创建原始类型的数组来轻松解决:

Tree<String>[] newChildrenArray = new Tree[newChildren.size()];
newChildrenArray.toArray(newChildren);
myTree.addChildren(newChildrenArray);

您可以让一个方法接受List,并让其中一个方法调用另一个:

public Tree<T> addChildren(Iterable<Tree<T>> children) {
    for (Tree<T> child : children) {
        if (this.children.add(child)) {
            child.setParent(this);
        }
    }
    return this;
}
public Tree<T> addChildren(Tree<T>... children) {
    return addChildren(Arrays.asList(children));
}

最新更新