Яку колекцію Java я повинен використовувати?


127

У цьому запитанні Як я можу ефективно вибрати контейнер «Стандартна бібліотека» на C ++ 11? - це зручна діаграма потоку, яку слід використовувати при виборі колекцій C ++.

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

Які ресурси та "шпаргалки" доступні, щоб допомогти людям вибрати правильну колекцію, яку використовуватимуть під час програмування на Java? Як люди знають, які реалізації списків, наборів та карт вони повинні використовувати?


У книзі Java Generics and Collection (Naftalin & Wadler) є розділ про це.
Крістоф Руссі

Відповіді:


292

Оскільки я не зміг знайти подібну блок-схему, я вирішив зробити її сам.

Ця діаграма не намагається охопити такі речі, як синхронізований доступ, безпека потоку тощо тощо або застарілі колекції, але вона охоплює 3 стандартних набору s, 3 стандартних Map s та 2 стандартних List s.

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

Це зображення було створено для цієї відповіді та ліцензується за міжнародною ліцензією Creative Commons Attribution 4.0. Найпростіша атрибуція - це посилання на це запитання чи цю відповідь.

Інші ресурси

Мабуть, найбільш корисна інша довідка - це наступна сторінка з документації про oracle, яка описує кожну колекцію .

HashSet vs TreeSet

Існує детальне обговорення, коли використовувати HashSetабо TreeSetтут: Hashset vs Treeset

ArrayList vs LinkedList

Детальна дискусія: Коли використовувати LinkedList через ArrayList?


Приємно! Але я повинен не погодитися з вашими рішеннями LinkedListпроти ArrayList. По-перше, якщо список має значні розміри, LinkedListбажано. LinkedListмає один елемент накладних витрат, тому він асимптотично гірший з точки зору споживання пам'яті, ніж an ArrayList. Крім того, якщо більша частина доступу знаходиться в кінці списку, ArrayListпереважніше, оскільки воно забезпечує доступ до випадкових елементів у постійному часі. Доступ до nth-го елемента a LinkedList- це O(n)операція. ... Насправді, рішення про використання зв'язаного списку майже завжди повинно бути "ні".
Метт Бал

2
@MattBall Здебільшого я згоден з вами. Однак Java LinkedList- це подвійний зв'язаний список, тому доступ як на початку, так і в кінці обох швидкий. Ви зауважите, що з усіх галузей, що відповідають усім трьом питанням, слід відповісти "так", перш ніж я порекомендую скористатися цим запитом, LinkedList- іншими словами, я погоджуюся з вами, що у більшості випадків відповідь "ні". Такі речі, як черги та dequeues, де ви постійно додаєте та видаляєте речі з кінців області списку, для яких добре використовувати LinkedList.
Тім Б

Використання пам'яті @MattBall - набагато складніша ситуація, оскільки в той час як LinkedListвикористовується більше пам'яті на елемент ... ArrayListніколи не вивільняється пам'ять. Це означає, що якщо у вас є список, який іноді збільшується до величезних розмірів, але зазвичай малий, то показник ArrayListдасть гірші показники пам'яті. Сама витрата на пам'ять Listзазвичай (хоча і не завжди) мала, порівняно з елементом, який вона містить.
Тім Б

Map<K,V>не є частиноюjava.util.collection
Меджрай Малік

@MehrajMalik Хм, маркування неоднозначне я згоден. Я мав на увазі колекцію всередині java.util. тобто java.util. * вставте сюди ім'я колекції *
Тім B

66

Короткий зміст основних колекцій, що не супроводжуються, не синхронізовані

Collection: Інтерфейс, що представляє не упорядкований "мішок" предметів, який називається "елементи". "Наступний" елемент не визначений (випадковий).

  • Set: Інтерфейс, що представляє Collectionбез копій.
    • HashSet: SetПідкріплений Hashtable. Найшвидше і найменше використання пам'яті, коли замовлення неважливо.
    • LinkedHashSet: A HashSetз додаванням пов'язаного списку для асоціювання елементів у порядку вставки . Елемент "наступний" - це наступний за останнім часом вставлений елемент.
    • TreeSet: A, Setде елементи впорядковуються за допомогою Comparator(як правило, природного впорядкування ). Найменше і найбільше використання пам'яті, але необхідне для замовлення на основі порівняння.
    • EnumSet: Надзвичайно швидкий та ефективний Setпідхід для одного типу перерахунку.
  • List: Інтерфейс, який представляє 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: А, Mapколи ключі не упорядковані та підтримуються a Hashtable.
    • LinkedhashMap: Ключі впорядковані по порядку вставки .
    • TreeMap: А, Mapколи ключі впорядковуються Comparator(як правило, природним впорядкуванням).
  • Queue: Інтерфейс, який представляє Collectionелементи, де елементи, як правило, додаються в один кінець і видаляються з іншого (FIFO: first-in, first-out).
  • Stack: Інтерфейс, який представляє Collectionелементи, де елементи, як правило, додаються (висуваються) та видаляються (вискакують) з того самого кінця (LIFO: last-in, first-out).
  • Deque: Скорочене слово "подвійна черга", зазвичай вимовляється "дека". Зв'язаний список, який зазвичай додається і читається з будь-якого кінця (не з середини).

Основні схеми колекції:

діаграма

Порівняння вставки елемента з ArrayListта LinkedList:

діаграма


2
Краще коротко літнє, що можна дістатись куди завгодно :)
roottraveller

11

Ще простіша картина тут. Навмисно спрощено!

  1. Збір - це все, що містить дані, що називаються "елементи" (одного типу). Нічого більш конкретного не передбачається.

  2. Список - це індексований набір даних, де кожен елемент має індекс. Щось схоже на масив, але більш гнучко.

    Дані у списку зберігають порядок вставки.

    Типова операція: отримати n-й елемент.

  3. Набір - це мішок елементів , кожен елемент лише один раз (елементи розрізняють за їхequals()методом.

    Дані в наборі зберігаються здебільшого просто для того, щоб знати, які дані є.

    Типова операція: повідомте, чи присутній елемент у списку.

  4. Карта - це щось на зразок Списку, але замість доступу до елементів за допомогою їх цілого індексу, ви отримуєте доступ до них за їх ключем , який є будь-яким об’єктом. Як і масив у PHP :)

    Дані на карті можна шукати за їх ключем.

    Типова операція: отримайте елемент за його ідентифікатором (де ID будь-якого типу, не тільки intяк у списку).

Відмінності

  • Встановити та карта: у Встановіть пошук даних самостійно , в той час як у Картах за їх ключем .

  • Список та карта: у списку ви отримуєте доступ до елемента за їх intіндексом (позиція у списку), тоді як у карті за їх ключем, який os будь-якого типу (як правило: ідентифікатор)

  • Список і встановити: у списку елементи пов'язані за своїм положенням і можуть бути дублікатами, в той час як у Набір елементи просто "присутні" (pr немає) та є унікальними (у значенні equals()або compareTo()для SortedSet)


1

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

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


1

Карта

Якщо я вибрав Map, я склав цю таблицю, узагальнюючи особливості кожної з десяти реалізацій, в комплекті з Java 11.

Таблиця реалізацій карт на Java 11, порівняння їх особливостей



-2

Яку колекцію Java я повинен використовувати?

Це залежить від того, яку проблему ви намагаєтеся вирішити або які вимоги ви маєте.

Приклади:

  1. Ви хочете, щоб елементи сортувались під час їх зберігання? HashSet
  2. Ви хочете зберігати пари (ключ, значення)? HashMap
  3. Чи хочете зберегти порядок елементів, які вставлені? ArrayList, LinkedList
  4. Чи хочете ви сортувати клавіші (Ключ, Значення)? - сильний текст
  5. Ви хочете реалізувати стек для вирішення вашої проблеми? - Стек
  6. Ви хочете мати доступ до FIFO (First in First out)? - Черга
  7. Ви хочете зберігати лише УНІКАЛЬНІ елементи? - HashSet
  8. Ви хочете дозволити ключ як "Null" під час зберігання (Key, Value)? - HashMap
  9. Ви хочете, щоб значення NULL для пари (ключ, значення) не було? HashTable

Навіть із сильним текстом у пункті 4, заміненим, скажімо, ConcurrentSkipListMap (K, V) , що ця відповідь додає до графіка рішення Тіма Б , щоб змінити "описи короткого списку" альтералмінда ?
сіра борода

Ваша перша точка, HashSet не сортує дані, навіть порядок вставки не підтримується. Ви повинні змінити його на TreeSet
Saurabh Mishra
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.