java: возврат коллекции

каков наилучший способ вернуть коллекцию на Java?

Я должен позволить абонента коллекцию добавить? Или просто верните List<> или Set<> элементов? Или как?

public class Item { ... }

public class SomeOtherClass
{
  private List<Item> myItems;

  public List<Item> getItems()
  { 
     return Collections.unmodifiableList(this.myItems); 
  }
  public void collectItems(Collection<? super Item> target)
  {
     target.addAll(myItems);
  }
}

Примечание: приведенный выше пример предполагает предварительное существование списка, который может быть немедленно возвращен. Меня также интересует соответствующий ответ, когда такой список ранее не существовал и должен быть сгенерирован, когда вызывающий абонент вызывает getItems () или collectItems(). (Я переименовал collectItems на основе пункта, поднятого Николаем.)

7 ответов


Я просто предпочел бы List<Item> getItems() метод. Нет никакого реального преимущества для void getItems(Collection<? super Item> target) на абонент просто делает myCollection.addAll(foo.getItems()) производительность или иным образом. Collections.unmodifiableXYZ только создает оболочку, а не полную копию коллекции, поэтому, если оболочка используется немедленно и отбрасывается, она никогда не выйдет из первого поколения и будет быстро собрана с небольшими накладными расходами.

если коллекция предметов не всегда реализована, вы можете рассмотреть возможность возврата getItems Iterable<Item> когда вы не знаю, сколько там предметов. Если вы знаете количество элементов и можете написать для них итератор, то легко написать пользовательский подкласс AbstractCollection и вернуть, что.


лучше (если нет проблем с производительностью) вернуть результат в функции через return. Таким образом, становится яснее, что происходит.

Если вы выберете второй вариант (сборник заливки клиента), чем было бы лучше переименовать функцию getItems что-то вроде fillWithItems чтобы избежать неоднозначного кода.

также не забывайте о JavaBeans и его конвенции.


вы должны вернуть коллекцию. Это более распространенный подход в Java, чем использовать параметры in/out. Я не вижу причин, по которым будет штраф за производительность для возврата большой коллекции, и это будет намного более чистый код.


учитывая, как работает Java, вы обычно ожидаете возвращаемую версию.

однако, если вам нужен контроль над тем, какой тип коллекции создается, вы бы сделали версию, где вы передаете ее в качестве аргумента.

обычно ничто не должно заботиться о том, какой тип коллекции создается, поэтому вы должны обычно идти с возвращаемой версией. Кстати, хорошее использование unmodifiableList.


Примечание: возврат и возврат списка имеют разные последствия.

набор не имеет дубликатов и заданного порядка. Добавление элемента в набор может привести к другому порядку элементов.

список может содержать дубликаты, и добавление элемента (как правило) не изменит общий порядок списка.

Что касается того, как вы возвращаете список, я бы использовал первую форму:

public List<Item> getItems()
{ 
   return Collections.unmodifiableList(this.myItems); 
}

Я не могу придумать ситуации, где последняя форма принесла бы пользу. Список не похож на массив, в котором пространство может быть предварительно выделено. Таким образом, нет никакой экономии производительности, передавая список.


единственная причина, по которой я могу придумать, чтобы заполнить существующую коллекцию, а не создавать новую, - это когда у вас есть проблемы с типом объекта в коллекции. Как и функция библиотеки Java toArray (Object[] a), где программа не знает во время компиляции, каким будет соответствующий тип элементов массива, поэтому она не может просто вернуть, например, строку[]. Поэтому вместо этого у них есть вызывающий абонент в массиве с соответствующим типом элементов, и они заполняют что.

90% времени вы точно знаете, какие типы объектов вы хотите вернуть, поэтому вы можете просто сделать это.


вы можете изменить свою подпись, чтобы вернуть коллекцию или Iterable. Для возврата Iterable вы можете вернуть что-то новое-Iterable(myItems.iterator ()) вместо myItems напрямую, чтобы избежать клиента, возможно, пытающегося привести к списку (и изменить его). Если вы не хотите, чтобы они изменяли список, также подумайте о возвращении итератора, но обратите внимание, что Iterable лучше, поскольку вы можете напрямую использовать их в циклах for-each.

возвращение Iterable оба делает ваше намерение понятно и в приведенном выше примере, предотвращает изменения. Единственный вывод заключается в том, что вы потеряли случайный доступ, который может быть или не быть проблемой для ваших нужд.