Мы изучаем интерфейс Collection, и мне было интересно, есть ли у вас все хорошие советы для его общего использования? Что вы можете сделать с коллекцией, которую вы не можете сделать с массивом? Что вы можете сделать с массивом, который вы не можете сделать с помощью Collection (помимо разрешения дубликатов)?
Интерфейс коллекции против массивов
Ответ 1
Легко, если вы думаете об этом так: Коллекции лучше, чем массивы объектов, в основном во всех возможных целях.
Вы можете предпочесть List<Foo>
над Foo[]
, когда это возможно. Рассмотрим:
- Коллекция может быть изменчивой или неизменной. Непустой массив всегда должен быть изменен.
- Коллекция может быть потокобезопасной; даже одновременно. Массив никогда не будет безопасным для публикации в нескольких потоках.
- Коллекция может разрешать или запрещать нулевые элементы. Массив всегда должен иметь нулевые элементы.
- Коллекция безопасна для типов; массив нет. Поскольку в процессе выполнения может возникнуть "поддельная" ковариация массивов,
ArrayStoreException
. - Коллекция может содержать невосстанавливаемый тип (например,
List<Class<? extends E>>
илиList<Optional<T>>
). С помощью массива вы получаете предупреждения компиляции и запутывающие исключения во время выполнения. - У коллекции есть полностью скомпонованный API; массив имеет только set-at-index, get-at-index и length.
- Коллекция может иметь виды (немодифицируемые, сублисты, фильтры...). Нет такой удачи для массива.
- Список или набор методов
equals
,hashCode
иtoString
делают то, что ожидают пользователи; эти методы в массиве делают что-либо, кроме того, что вы ожидаете, - общий источник ошибок. - Из-за всех вышеперечисленных причин сторонние библиотеки, такие как Guava, не будут беспокоиться о добавлении дополнительной поддержки массивов, фокусируясь только на коллекциях, поэтому есть сетевой эффект.
Массивы объектов никогда не станут первоклассными гражданами на Java.
Некоторые из приведенных выше причин более подробно описаны в "Эффективном Java", "Второе издание", начиная со страницы 119.
Итак, зачем вам когда-либо использовать массивы объектов?
- Вам нужно взаимодействовать с API, который их использует, и вы не можете исправить этот API
- поэтому конвертируйте в/из a
List
как можно ближе к этому API, как вы можете
- поэтому конвертируйте в/из a
- У вас есть надежный бенчмарк, который показывает, что вы на самом деле получаете лучшую производительность с ними
- но тесты могут лежать и часто выполнять
- Я не могу придумать никаких других причин.
Ответ 2
В основном речь идет о желаемом уровне абстракции.
Большинство коллекций могут быть реализованы с точки зрения массивов, но для вашего удобства они предоставляют множество других методов. Большинство реализаций коллекции, которые я знаю, например, могут расти и сокращаться в зависимости от спроса или выполнять другие "высокоуровневые" операции, которые базовые массивы не могут.
Предположим, например, что вы загружаете строки из файла. Вы не знаете, сколько символов новой строки содержится в файле, поэтому вы не знаете, какой размер использовать при распределении массива. Поэтому лучше выбрать ArrayList.
Ответ 3
Подробности находятся в суб-интерфейсах Collection, таких как Set, List и Map. Каждый из этих типов имеет семантику. Набор обычно не может содержать дубликатов и не имеет понятия порядка (хотя некоторые реализации выполняются), следуя математической концепции набора. Список ближе всего к массиву. Карта имеет определенное поведение для push и get. Вы нажимаете объект по его ключу, и вы получаете с тем же ключом.
В реализациях каждого типа коллекции еще больше деталей. Например, любая коллекция, основанная на хеше (например, HashSet, HasMap), основана на методе hashcode(), который существует на любом объекте Java.
Вы можете моделировать семантику любого типа коллекции на основе массива, но для этого вам нужно будет написать много кода. Например, чтобы вернуть карту с массивом, вам нужно написать метод, который помещает любой объект, введенный в вашу карту, в конкретное ведро в массиве. Вам нужно будет обрабатывать дубликаты. Для массива, моделирующего набор, вам нужно написать код, чтобы не допускать дубликатов.
Ответ 4
Интерфейс Collection - это просто базовый интерфейс для специализированных коллекций. Я еще не знаю класс, который просто реализует Collection; вместо этого классы реализуют специализированные интерфейсы, которые расширяют Collection. Эти специализированные интерфейсы и абстрактные классы обеспечивают функциональность для работы с наборами (уникальными объектами), растущими массивами (например, ArrayList), картами с ключом и т.д., Которые вы не можете делать из коробки с массивом. Тем не менее, повторение с помощью массива и установка/чтение элементов из массива остаются одним из самых быстрых методов обработки данных в Java.
Ответ 5
Одним из преимуществ является интерфейс Iterator. Это все Коллекции реализуют Итератор. Итератор - это объект, который знает, как выполнять итерацию по данной коллекции, и представить программисту единый интерфейс, независимо от базовой реализации. То есть связанный список проходит иначе, чем бинарное дерево, но итератор скрывает эти отличия от программиста, что облегчает программисту использование той или иной коллекции.
Это также приводит к возможности использования различных реализаций коллекций взаимозаменяемо, если код клиента нацелен на интерфейс Collection.