Что лучший способ состоит в том, чтобы возвратить набор в Java?
Я должен позволить вызывающей стороне обеспечивать набор для добавления к? Или просто возвратите a 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 на основе вопроса, поднятого Mykola.)
Я просто предпочитаю метод List
. Нет никакого реального преимущества в void getItems(Collection super Item> target)
над вызывающим, просто выполняющим myCollection.addAll(foo.getItems())
или другим способом. Collections.unmodifiableXYZ
только создаёт обёртку, а не полную копию коллекции, поэтому если обёртка используется немедленно и отбрасывается, то она никогда не выйдет из первого поколения и будет собрана быстро, с небольшими накладными расходами.
Если коллекция элементов не всегда реализуется, вы можете рассмотреть возможность возврата getItems Iterable
, когда вы не знаете, сколько элементов там есть. Если вы знаете количество элементов и можете написать итератор для них, то легко написать пользовательский подкласс AbstractCollection
и вернуть его.
Вы должны вернуть коллекцию. Это более распространенный подход в Java, чем использовать параметры входа / вывода. Я не вижу никаких причин, что был бы штраф производительности для возврата большой коллекции, и это будет гораздо более чистый код.
Учитывая то, как работает Java, вы обычно ожидаете возвратную версию.
Однако, если вам нужен контроль над тем, какой тип коллекции создается, то вы должны сделать версию, в которой вы передаете ее в качестве аргумента.
Обычно ничто не должно заботиться о том, какой тип коллекции создается, так что, как правило, вы должны использовать возвращаемую версию. Кстати, полезно использовать неизменяемый список.
Примечание. Возвращение набора и возврата списка имеет разные последствия.
Набор не имеет дупликатов и не указанного порядка. Добавление элемента на множество может привести к другому порядку элементов.
Список может содержать дубликаты и добавление элемента не будет (вообще) изменить общий порядок списка.
Что касается того, как вы возвращаете список, я бы использовал первую форму:
public List<Item> getItems()
{
return Collections.unmodifiableList(this.myItems);
}
Я не могу придумать ситуацию, когда последняя форма будет любого выгоды. Список не похож на массив, где пространство может быть предварительно выделено. Таким образом, нет экономии производительности, проходя в списке.
Единственная причина, по которой я могу думать о том, чтобы заполнить существующую коллекцию, а не создавать новую, это когда у вас возникают проблемы с типом объекта в коллекции. Как и в случае с функцией Java библиотеки toArray(Object[] a), где программа на этапе компиляции не знает, какого типа будут элементы массива, так и не может просто вернуть, например, String[]. Поэтому вместо этого в массиве с соответствующим типом элементов передается вызов, и они заполняют его.
90% времени вы точно знаете, какие типы объектов вы хотите вернуть, так что вы можете просто сделать это.
Вы можете поменять подпись, чтобы вернуть коллекцию или отсрочку. Для возврата Iterable, вы можете вернуть что-то новое - Iterable(myItems.iterator()) вместо myItems напрямую, чтобы клиент, возможно, не пытался проиграть список (и изменить его). Если вы не хотите, чтобы они модифицировали список, также подумайте о возвращении итератора, но обратите внимание, что Iterable лучше, так как вы можете напрямую использовать его в for-each циклах.
Возвращение итератора и то, и другое делает ваши намерения ясными, а в приведенном выше примере предотвращает модификацию. Единственным намеком является то, что вы потеряли случайный доступ, что может быть проблемой для ваших нужд.
. Лучше (если не возникают проблемы с производительностью) возвращать результат в функции через return
. Так становится более понятно, что происходит.
Если вы выберете второй вариант (заполнить коллекцию клиента), было бы лучше переименовать функцию из getItems
в что-то вроде fillWithItems
, чтобы избежать неоднозначного кода.
Также не забывайте о JavaBeans и их соглашениях.