Какую коллекцию Java мне следует использовать?

127

В этом вопросе Как я могу эффективно выбрать контейнер стандартной библиотеки в C ++ 11?- это удобная блок-схема, которую можно использовать при выборе коллекций C ++.

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

Какие ресурсы и «шпаргалки» доступны, чтобы помочь людям выбрать правильную коллекцию для использования при программировании на Java? Как люди узнают, какие реализации List, Set и Map им следует использовать?

Тим Б
источник
В книге Java Generics and Collections (Naftalin & Wadler) есть глава об этом.
Christophe

Ответы:

293

Поскольку мне не удалось найти подобную блок-схему, я решил сделать ее сам.

Эта блок-схема не пытается охватить такие вещи, как синхронизированный доступ, безопасность потоков и т. Д. Или устаревшие коллекции, но она охватывает 3 стандартных набора , 3 стандартных карты и 2 стандартных списка .

введите описание изображения здесь

Это изображение было создано для этого ответа и находится под международной лицензией Creative Commons Attribution 4.0. Самая простая атрибуция - это ссылка на этот вопрос или на этот ответ.

Другие источники

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

HashSet против TreeSet

Подробное обсуждение того, когда использовать, HashSetили TreeSetздесь: Hashset vs Treeset

ArrayList против LinkedList

Подробное обсуждение: когда использовать LinkedList вместо ArrayList?

Тим Б
источник
Ницца! Но я должен не согласиться с вашими решениями LinkedListпротив ArrayList. Во-первых, LinkedListпредпочтительно , если список значительный . LinkedListимеет накладные расходы на каждый элемент, поэтому он асимптотически хуже с точки зрения потребления памяти, чем ArrayList. Кроме того, если большая часть доступа находится в конце списка, ArrayListпредпочтительнее использовать элемент, поскольку он обеспечивает доступ к произвольным элементам с постоянным временем. Доступ к nth элементу a LinkedList- это O(n)операция. ... Фактически, решение использовать связанный список почти всегда должно быть отрицательным.
Мэтт Болл
2
@MattBall По большей части я с вами согласен. Однако Java LinkedList- это двусвязный список, поэтому доступ в начале и в конце выполняется быстро. Вы заметите, что из приведенных выше веток на все три вопроса необходимо ответить «да», прежде чем я рекомендую использовать LinkedList- другими словами, я согласен с вами, что в большинстве случаев ответ отрицательный. Такие вещи, как очереди и удаление из очереди, где вы постоянно добавляете и удаляете элементы с концов области списка, хороший вариант использования LinkedList.
Tim B
@MattBall Использование памяти - гораздо более сложная ситуация, поскольку, хотя LinkedListиспользует больше памяти на элемент ... ArrayListникогда не освобождает память. Это означает, что если у вас есть список, который иногда увеличивается до огромного размера, но обычно невелик, то производительность ArrayListпамяти будет хуже. Накладные расходы на память самого элемента Listобычно (хотя и не всегда) малы по сравнению с элементами, которые он также содержит.
Tim B
Map<K,V>не является частьюjava.util.collection
Мехрадж Малик 02
@MehrajMalik Хм, маркировка неоднозначна, согласен. Я имел в виду коллекцию внутри java.util. т.е. java.util. * вставьте сюда имя коллекции *
Тим Б.
66

Сводка основных несинхронизированных и одновременных коллекций

Collection: Интерфейс, представляющий неупорядоченный «мешок» элементов, называемый «элементами». «Следующий» элемент не определен (случайный).

  • Set: Интерфейс, представляющий Collectionбез дубликатов.
    • HashSet: А Setподкреплена Hashtable. Максимально быстрое и минимальное использование памяти, при заказе неважно.
    • LinkedHashSet: A HashSetс добавлением связанного списка для связывания элементов в порядке вставки . «Следующий» элемент - это последний вставленный элемент.
    • TreeSet: A, Setгде элементы упорядочены по a Comparator(обычно естественный порядок ). Самое медленное и максимальное использование памяти, но необходимо для упорядочивания на основе компаратора.
    • EnumSet: Чрезвычайно быстрый и эффективный, Setнастроенный для одного типа перечисления.
  • List: Интерфейс, представляющий a Collection, элементы которого упорядочены, и каждый имеет числовой индекс, представляющий его позицию, где ноль - это первый элемент, а (length - 1)- последний.
    • ArrayList: ListПоддерживается массивом, где длина массива (называемая «емкостью») не меньше количества элементов («размер» списка). Когда размер превышает емкость (при (capacity + 1)-thдобавлении элемента), массив воссоздается с новой емкостью - это (new length * 1.5)восстановление выполняется быстро, поскольку оно использует System.arrayCopy(). Удаление и вставка / добавление элементов требует, чтобы все соседние элементы (справа) были перемещены в это пространство или из него. Доступ к любому элементу происходит быстро, так как (element-zero-address + desired-index * element-size)для определения его местоположения требуется только расчет . В большинстве случаев , ArrayListпредпочтительно больше LinkedList.
    • LinkedList: Объект, Listподдерживаемый набором объектов, каждый из которых связан со своими «предыдущими» и «следующими» соседями. А LinkedListтакже является Queueи Deque. Доступ к элементам осуществляется, начиная с первого или последнего элемента и перемещаясь, пока не будет достигнут желаемый индекс. Вставка и удаление, как только желаемый индекс достигнут посредством обхода, является тривиальным делом повторного сопоставления только ссылок непосредственного соседа, чтобы указать на новый элемент или обойти теперь удаленный элемент.
  • Map: Интерфейс, представляющий, Collectionгде каждый элемент имеет идентифицирующий «ключ» - каждый элемент представляет собой пару «ключ-значение».
    • HashMap: A, Mapгде ключи неупорядочены и поддерживаются Hashtable.
    • LinkedhashMap: Ключи отсортированы по порядку вставки .
    • TreeMap: A, Mapгде ключи расположены в порядке Comparator(обычно естественный порядок).
  • Queue: Интерфейс, который представляет собой, Collectionгде элементы, как правило, добавляются к одному концу и удаляются с другого (FIFO: first-in, first-out).
  • Stack: Интерфейс, который представляет собой, Collectionгде элементы, как правило, добавляются (выталкиваются) и удаляются (выталкиваются) с одного и того же конца (LIFO: последний пришел, первый ушел).
  • Deque: Сокращение от «двусторонняя очередь», обычно произносится как «колода». Связанный список, который обычно добавляется и читается только с любого конца (а не с середины).

Основные схемы сбора:

диаграмма

Сравнение вставки элемента с помощью ArrayListи LinkedList:

диаграмма

aliteralmind
источник
2
Лучшее вкратце, что можно найти где угодно :)
roottraveller
11

Здесь еще более простая картина. Умышленно упрощено!

  1. Коллекция - это все, что хранит данные, называемые «элементами» (одного типа). Ничего более конкретного не предполагается.

  2. Список - это индексированная коллекция данных, каждый элемент которой имеет индекс. Что-то вроде массива, но более гибкое.

    Данные в списке сохраняют порядок вставки.

    Типовая операция: получить n-й элемент.

  3. Набор - это набор элементов , каждый элемент только один раз (элементы различаются по ихequals() методу.

    Данные в наборе хранятся в основном для того, чтобы знать, какие данные там есть.

    Типичная операция: узнать, присутствует ли элемент в списке.

  4. Карта чем-то похожа на список, но вместо доступа к элементам по их целочисленному индексу выполучаетедоступ к ним по их ключу , которым является любой объект. Как и массив в PHP :)

    Данные на карте доступны для поиска по их ключу.

    Типичная работа: получить элемент по его ID (где ID любого типа, а не только intкак в случае со списком).

Различия

  • Набор и карта: в наборе вы ищите данные сами по себе , а на карте - по их ключу .

  • Список и карта: в списке вы получаете доступ к элементу по их intиндексу (позиции в списке), а в карте по их ключу, который имеет любой тип (обычно: ID)

  • Список и набор: в списке элементы связаны своим положением и могут дублироваться, в то время как в наборе элементы просто «присутствуют» (пр нет) и уникальны (в значении equals()или compareTo()для SortedSet)

Хонза Зидек
источник
1

Это просто: если вам нужно хранить значения с сопоставленными им ключами, используйте интерфейс Map, в противном случае используйте List для значений, которые могут дублироваться, и, наконец, используйте интерфейс Set, если вы не хотите, чтобы повторяющиеся значения в вашей коллекции.

Вот полное объяснение http://javatutorial.net/choose-the-right-java-collection , включая блок-схему и т. Д.

filip_j
источник
1

карта

При выборе a Mapя сделал эту таблицу, в которой суммировал функции каждой из десяти реализаций, связанных с Java 11.

Таблица реализаций карт в Java 11, сравнение их возможностей

Василий Бурк
источник
0

Общие коллекции, Общие коллекции введите описание изображения здесь

Александр Шпак
источник
-2

Какую коллекцию Java мне следует использовать?

Это зависит от того, какую проблему вы пытаетесь решить или какие у вас требования.

Примеры :

  1. Вы хотите, чтобы элементы сортировались при их сохранении? HashSet
  2. Вы хотите, чтобы пары (ключ, значение) сохранялись? HashMap
  3. Вы хотите, чтобы порядок элементов при вставке сохранялся? ArrayList, LinkedList
  4. Вы хотите, чтобы ключи в паре (ключ, значение) были отсортированы? - сильный текст
  5. Вы хотите реализовать стек для решения вашей проблемы? - Стек
  6. Вы хотите иметь доступ FIFO (первым пришел - первым ушел)? - Очередь
  7. Вы хотите, чтобы хранились только УНИКАЛЬНЫЕ элементы? - HashSet
  8. Вы хотите разрешить ключ как "Null" при сохранении (Key, Value)? - HashMap
  9. Вам нужны значения No NULL для пары (Key, Value)? Хеш-таблица
Авирал Кумар
источник
Даже если сильный текст в пункте 4 заменен, скажем, ConcurrentSkipListMap (K, V) , что этот ответ добавляет к графу решений Тима Б , к «кратким описаниям» aliteralmind ?
greybeard
Ваше первое замечание: HashSet не сортирует данные, даже порядок вставки не поддерживается. Вы должны изменить его с помощью TreeSet
Мишра