Яка найшвидша колекція Java з основними функціоналами черги?


75

Яка найшвидша колекція на Java?

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

Без обмеження розмір теж важливий.

У цій колекції будуть об’єкти всередині нього.

В даний час я використовую ArrayDeque, оскільки я бачу, що це швидше здійснення черги.


10
Якщо порядок не важливий, ви не шукаєте черги.
BoltClock

В даний час я додаю у фінал і отримую з самого початку (як Черга), але якщо я можу вийняти всі елементи по одному, я можу використовувати іншу Колекцію.
Ренато Діньхані,

3
"... передчасна оптимізація - корінь усього зла"
мере

56
вибір правильної колекції - це не передчасна оптимізація.
Божо

7
BoltClock, це неправильно для черги з великим Q в Java. Це означає лише "змінну колекцію з головним елементом". Перечитайте java.util.Queue.
Кевін Бурріллон,

Відповіді:


95

ArrayDequeнайкраще. Дивіться цей орієнтир , який випливає з цього допису в блозі про результати порівняльного аналізу. ArrayDequeне має накладних витрат на виділення вузлів, LinkedListа також накладних витрат на зміщення вмісту масиву, залишеного при видаленні, що ArrayListмає. У тесті він працює приблизно в 3 рази , а також LinkedListдля великих черг і навіть трохи кращий, ніж ArrayListдля порожніх черг. Для найкращої продуктивності ви, мабуть, захочете надати їй початкову ємність, достатню для вміщення тієї кількості елементів, яку вона, швидше за все, вміщає одночасно, щоб уникнути багатьох розмірів.

Схоже, що між ArrayListі LinkedList, це залежить від середньої кількості загальної кількості елементів, яку черга буде містити в будь-який момент часу, і що LinkedListб'ється, ArrayListпочинаючи з приблизно 10 елементів.


ArrayList, що використовується як стек, повинен бути таким самим, як ArrayDeque, початкова ємність сильно впливає на продуктивність. Занадто багато означає більше пам'яті для виділення та збору, занадто мало означає більше копій (але це загалом краще, ніж занадто великий для жорстких циклів). Я не міг побачити джерело тесту, чи доступне воно?
bestsss

@bestsss: Так, використання як стек ArrayListбуде приблизно еквівалентним, хоча ArrayDequejavadoc припускає, що це може бути трохи швидше. І так, з огляду на вимоги у питанні, використання, подібне до стеку, буде справно працювати. Орієнтовний показник призначений спеціально для використання черги FIFO (ви можете побачити приклад коду у зв’язаному дописі в блозі).
ColinD

7
Я розумію, що це питання давнє, але обидва ваші посилання мертві. Чи існують альтернативні URL-адреси?
рат

4
Оскільки у мене була та ж проблема, що і @rath, я просканував оригінальний блог і знайшов оригінальну статтю: https://publicobject.com/2010/07/07/caliper_confirms_reality_linked_list_vs_array_list/ . На жаль, якщо я спробую побачити результати порівняння, я отримую 401 - несанкціоновану помилку.
окрамот

3
Ось також ще один експеримент, який підтверджує, що ArrayDeque в 3 рази швидший за LinkedList
Dheeru Mundluru

6

Ви можете використовувати a java.util.LinkedList- він подвійно зв’язаний і циркулярний, тому додавання до одного кінця та взяття з іншого - O (1)

Яку б реалізацію ви не вибрали, зверніться до неї за Queueінтерфейсом, щоб ви могли легко змінити її, якщо виявиться, що вона не відповідає вашому випадку (якщо, звичайно, черга - це те, що вам потрібно в першу чергу)

Оновлення: відповідь Коліна показує еталон, який робить висновок, що ArrayDequeкраще. Обидва мають операції O (1), але LinkedListстворює нові об'єкти (вузли), які незначно працюють. Оскільки обидва мають O (1), я не думаю, що було б занадто неправильно вибирати LinkedList.


2
ArrayDequeхоча об'єктивно краще.
ColinD

@ColinD - Я бачив, але чому? Через створення об’єкта (вузлів) у списку linekdlist? Обидва здаються O (1)
Божо

1
@ColinD @Bozho Так само змінюється розмір масиву в ArrayDeque. Справжнім розглядом тут є алгоритмічна складність. Все, що включає масив, має значення O (N) для додавання / видалення, все, що включає посилання, - O (1).
user207421

16
@EJP: ArrayDeque це O (1) для додавання та видалення на передній / кінцевій панелях (тобто, коли використовується як черга або стек), оскільки це круговий масив і в цих випадках нічого не копіює. Крім того, зміна розміру - це випадкова операція, якої часто можна уникнути за допомогою відповідної початкової потужності. LinkedListНакладні витрати на створення додаткового об'єкта (плюс збір сміття цього об'єкта) впливають на кожне додавання / видалення в черзі. Орієнтовний показник, який я зв’язав, показує, що він постійно втричі швидший, ніж a LinkedList.
ColinD

1
O(1) != O(1). O()це просто міра складності, а не часу виконання. Операція, яка завжди займає 5 років, незалежно від nє O(1), як і операція, яка завжди займає 5 мс. Я волів би використовувати той, який займає 5 мс. Навіть операція, яка займає 5 мс на елемент (що є O(n)), буде кращою, ніж 5-річна операція, якщо nвона не стане занадто великою.
Ерік Г. Хагстром,

0

ConcurrentLinkedDeque - найкращий вибір для багатопотокової черги

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