Java: возвращение коллекции - PullRequest
6 голосов
/ 01 февраля 2010

Какой лучший способ вернуть коллекцию в 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 (). (Я переименовал коллекционные элементы в соответствии с вопросом, поднятым Николаем.)

Ответы [ 7 ]

12 голосов
/ 01 февраля 2010

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

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

Также не забывайте о JavaBeans и его соглашении.

6 голосов
/ 01 февраля 2010

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

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

0 голосов
/ 01 февраля 2010

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

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

0 голосов
/ 01 февраля 2010

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

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

0 голосов
/ 01 февраля 2010

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

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

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

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

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

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

0 голосов
/ 01 февраля 2010

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

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

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

0 голосов
/ 01 февраля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...