Почему ArrayDeque лучше, чем LinkedList
Я пытаюсь понять почему ArrayDeque Java лучше, чем LinkedList Java поскольку они оба реализуют интерфейс Deque.
Я почти не вижу, чтобы кто-то использовал ArrayDeque в своем коде. Если кто-то проливает больше света на то, как реализуется ArrayDeque, это было бы полезно.
Если я понимаю, я буду более уверенно использовать его. Я не мог четко понять реализацию JDK относительно того, как она управляет ссылками head и tail.
7 ответов
связанные структуры, возможно, являются худшей структурой для итерации с пропуском кэша для каждого элемента. Кроме того, они потребляют гораздо больше памяти.
Если вам нужно добавить/удалить в оба конца, ArrayDeque значительно лучше, чем связанный список. Произвольный доступ каждый элемент также O (1) для циклической очереди.
только лучше операция это удаление текущего элемента во время итерации.
Я считаю, что основным "узким местом" в LinkedList
Это тот факт, что всякий раз, когда вы нажимаете на любой конец deque, за сценой реализация выделяет новый узел связанного списка, который по существу включает JVM/OS, и это дорого. Кроме того, всякий раз, когда вы поп с любого конца, внутренние узлы LinkedList
получить право на сбор мусора,и это больше работы за кулисами.
Кроме того, поскольку узлы связанного списка выделены здесь и там, использование кэша процессора не будет предоставить много пользы.
если это может представлять интерес, у меня есть доказательство того, что добавление элемента в ArrayList
или ArrayDeque
работает в амортизированное постоянное время; обратитесь к этой.
ArrayDeque
является новым С Java 6, поэтому многие коды (особенно проекты, которые пытаются быть совместимыми с более ранними версиями Java) не используют его.
в некоторых случаях это "лучше", потому что вы не выделяете узел для каждого элемента для вставки; вместо этого все элементы хранятся в гигантском массиве, который изменяется, если он заполняется.
все люди критикуют LinkedList
, подумайте о каждом другом парне, который использовал List
в Java, вероятно, использует ArrayList
и LinkedList
большую часть времени, потому что они были до Java 6 и потому, что это те, которые преподаются как начало в большинстве книг.
но это не значит, что я бы слепо принимать LinkedList
или ArrayDeque
'ы стороны. Если вы хотите знать, посмотрите на ниже benchmark сделал Брайан.
настройка теста считает:
- каждый тестовый объект представляет собой строку из 500 символов. Каждая строка-это отдельный объект в памяти.
- размер массива теста будет поменян во время тестов.
- для каждой комбинации размера массива / очереди-реализации выполняется 100 тестов и вычисляется среднее время на тест.
- каждый тест состоит из заполнения каждой очереди всеми объектами, а затем их удаления.
- мера время в миллисекундах.
Результат Теста:
- ниже 10 000 элементов, тесты LinkedList и ArrayDeque усреднены на уровне ниже 1 мс.
- по мере увеличения наборов данных различия между средним временем тестирования ArrayDeque и LinkedList увеличиваются.
- при тестовом размере 9,900,000 элементов подход LinkedList занял ~165% больше времени, чем ArrayDeque подход.
график:
вывод:
- если ваше требование хранит 100 или 200 элементов, то оно не сделало бы большая разница в использовании любой из очередей.
- однако, если вы разрабатываете на мобильном телефоне, вы можете использовать
ArrayList
илиArrayDeque
С хорошей догадкой максимальной емкости что список может потребоваться из-за строгой ограничение памяти. - существует много кода, написанного с помощью
LinkedList
поэтому будьте осторожны при решении использоватьArrayDeque
тем более, что он не реализуетList
интерфейс(я думаю, что это достаточно большая причина). Возможно, ваша кодовая база активно разговаривает с интерфейсом списка, скорее всего, и вы решите перейти кArrayDeque
. Используя его для внутренних реализаций может быть хорошей идеей...
доступ к элементу в ArrayDeque всегда быстрее по сравнению с LinkedList с O (1) для доступа к элементам. В связанном списке для поиска последнего элемента потребуется O(N).
ArrayDeque эффективен для памяти, так как вам не нужно отслеживать следующий узел, в отличие от связанного списка.
даже согласно документации java, было указано, что
ArrayDeque-реализация изменяемого размера массива интерфейса Deque. Двусторонней очередью массива имеют возможности ограничения; они растут по мере необходимости для поддержки использования. Они не являются потокобезопасными; в отсутствие внешней синхронизации они не поддерживают одновременный доступ несколькими потоками. Нулевые элементы запрещены. Этот класс, вероятно, будет быстрее стека при использовании в качестве стека и быстрее LinkedList при использовании в качестве очереди.
бенчмаркинг из этих двух доказывает, что ArrayDeque быстрее.
хотя ArrayDeque<E>
и LinkedList<E>
есть и реализован Deque<E>
интерфейс, но ArrayDeque использует в основном массив объектов E[]
для хранения элементов внутри своего объекта, поэтому он обычно использует индекс для размещения элементов головы и хвоста.
одним словом, он просто работает как Deque (со всем методом Deque), однако использует структуру данных массива. Что касается, какой из них лучше, зависит от того, как и где вы использовать их.
сложность времени для ArrayDeque для доступа к элементу составляет O(1), а для LinkList-O (N) для доступа к последнему элементу. ArrayDeque не является потокобезопасным, поэтому необходима ручная синхронизация, чтобы вы могли получить доступ к нему через несколько потоков, и поэтому они быстрее.