2014-09-15 3 views
1

Я пытаюсь реализовать родовое дерево.Использование общего списка в качестве параметров 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; 

С there is no way to create array of parametrized type в Java, наиболее очевидным решением является для перебора списка и добавления детей один за другим:

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

Но это неэффективное использование varargs. Поскольку я хочу сохранить класс Tree как можно проще, есть ли другой способ его реализации?

+1

Почему вы не создать функцию, которая принимает список деревьев? – cy3er

+0

@ cy3er Потому что я хочу, чтобы этот класс был как можно более простым. – Kao

+3

Я думаю, что добавление метода, который принимает список, так же просто, как и получается. Это, безусловно, самый простой подход, который я мог придумать, и когда дело доходит до читаемости/проверки, я определенно предпочитаю два разных метода для двух разных вещей (добавление детей и добавление деревьев). Как вы упоминаете _efficiency_: это не получается лучше, чем O (n) :) –

ответ

2

Это может быть легко решена путем создания массива сырого типа:

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

Вы можете иметь метод, принимающий в 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)); 
} 
1

Мой любимый способ для метода, чтобы принять как array и List (или даже лучше, 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)); 
} 

Также не бойтесь использовать некоторые wildcards, если вы хотите, чтобы позволить Tree<Animal> иметь Tree<Cat> как ребенок, то вам нужно будет изменить singatures на:

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

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

Используя текущую реализацию addChildren(), я не могу использовать подстановочные знаки. – Kao

+0

Как я уже сказал, это понадобится только в том случае, если вы хотите, чтобы «Дерево » было дочерним, и это потребует дополнительных изменений или может быть даже невозможным в зависимости от того, что вы хотите сделать с дети. Но * всегда * используйте подстановочные знаки в структурах только для чтения или только для записи, например 'Iterable > children', который должен хорошо работать с текущей реализацией. – kajacx

Смежные вопросы