Когда я должен принять параметр Iterable <T>против Collection <T>в Java? - PullRequest
68 голосов
/ 21 июля 2009

Каковы соображения использования Iterable<T> против Collection<T> в Java?

Например, рассмотрите возможность реализации типа, который в первую очередь касается хранения коллекции Foo s и некоторых связанных метаданных. Конструктор этого типа допускает однократную инициализацию списка объектов. (Метаданные могут быть установлены позже.) Какой тип должен принимать этот конструктор? Iterable<Foo> или Collection<Foo>?

Каковы соображения для этого решения?

Следуя шаблону, установленному библиотечными типами, такими как ArrayList (который может быть инициализирован любым Collection, но , а не и Iterable), я могу использовать Collection<Foo>.

Но почему бы не принять Iterable<Foo>, учитывая, что этого достаточно для потребностей инициализации? Зачем требовать от потребителя более высокого уровня функциональности (Collection), чем то, что строго необходимо (Iterable)?

Ответы [ 9 ]

63 голосов
/ 21 июля 2009

Многие из типов коллекций существовали до Iterable<T> (который был введен только в 1.5) - было мало причин для добавления конструктора для принятия Iterable<T> , а также Collection<T> но изменение существующего конструктора было бы серьезным изменением.

Лично я бы использовал Iterable<T>, если это позволяет вам делать все, что вы хотите. Он более гибок для абонентов и, в частности, позволяет вам относительно легко фильтровать / проецировать / и т. Д. С помощью Google Java Collections (и, без сомнения, похожих библиотек).

21 голосов
/ 21 июля 2009

An Iterable производит Iterator объектов. Объект Iterator по определению повторяет . Обратите внимание, что интерфейс Iterator не дает никаких обещаний относительно того, сколько раз можно вызвать next(), прежде чем hasNext() вернет false. Iterator может перебирать значения Integer.MAX_VALUE + 1 до того, как его метод hasNext() вернет false.

Однако Collection - это особая форма Iterable. Поскольку Collection не может иметь более чем Integer.MAX_VALUE элементов (в силу метода size()), естественно предполагается, что его объекты Iterator не будут повторяться над таким количеством элементов.

Поэтому, принимая Collection вместо Iterable, ваш класс может иметь некоторую гарантию того, сколько элементов передается. Это особенно желательно, если ваш класс сам по себе Collection.

Только мои два цента ...

9 голосов
/ 04 ноября 2012

Пользователи Spring Data JPA обнаружат, что Repositories возвращает коллекции типа Iterable<T>.

В проектах, над которыми я работал в прошлом, использующих Spring, я обнаружил, что необходимость работать с коллекцией после извлечения часто диктует, что Iterable<T> используется на бизнес-уровне, а не Collection<T> чтобы выбрать Объект T из коллекции.

Все коллекции - это Iterable (то есть интерфейсы, расширяющие интерфейс Collection, а не Map!), Поэтому использование Iterable на бизнес-уровне является всего лишь случаем обращения к коллекции с помощью ее super type и все еще позволяет использовать for-each для итерации.

Если вам нужно манипулировать содержимым коллекции, удобный метод позволит вам заполнить новый Collection, чтобы вы могли использовать contains(), remove() и т. Д. С исходными данными коллекции.

Кроме того, для этой цели предусмотрены удобные методы популярных сторонних API, таких как Google Guava и Apache Commons.

8 голосов
/ 21 июля 2009

Используйте самый общий интерфейс, который вы можете. Так как все, что вы собираетесь делать, это итерировать, то я бы сказал, что Iterable - это путь (поскольку он допускает ленивые итераторы и т. Д.). Вам не важно, откуда исходит итератор, поэтому не ограничивайте его больше, чем нужно.

4 голосов
/ 21 июля 2009

Некоторые конструкторы, например ArrayList (Collection c), используйте метод toArray () класса Collection для эффективности.

3 голосов
/ 28 июля 2009

См. «Почему так много внимания уделяется Итераторам и Итерабелам?» на FAQ по Google Collection для достойного аргумента для предпочтения Итераторов, особенно когда имеешь дело с большим количеством данных. Одна аналогия, которая могла бы помочь, - это подумать о разнице между прямыми курсорами только для чтения и прокручиваемыми курсорами.

2 голосов
/ 21 июля 2009

Если вы выберете Collection, то ваш класс может быть инициализирован только из коллекции, если вы выберете Iterable, вы можете инициализировать либо из коллекции, либо итеративной.

Поскольку усилия и производительность для обоих будут одинаковыми, имеет смысл принять Iterable в конструкторе.

0 голосов
/ 21 июля 2009

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

0 голосов
/ 21 июля 2009

Согласно принципу наименьшего удивления, вы должны эмулировать шаблон коллекции Java и взять аргумент конструктора Collection arg. Люди, которые придут за вами, будут немного менее озадачены.

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