LinkedHashMap vs HashMap!= LinkedList vs ArrayList
Я прочитал, что LinkedHashMap имеет более быструю итерационную скорость, чем HashMap, потому что ее элементы дважды связаны друг с другом. Кроме того, благодаря этому LinkedHashMap работает медленнее при вставке или удалении элементов. Предположительно, потому что эти ссылки также необходимо обновить.
Хотя я вижу аналогию с LinkedList vs ArrayList, поскольку элементы LinkedList также дважды связаны, я читал, что он выполняет итерацию медленнее, чем ArrayList, и имеет более быструю время вставки и удаления.
Почему это? Возможно, я где-то ошибаюсь?
Ура!
Ответы
Ответ 1
Аналогия не работает. LinkedList и ArrayList - две несвязанные реализации списка. Однако LinkedHashMap представляет собой ту же структуру данных, что и HashMap, но с привязанным к ней LinkedList, чтобы сделать итерацию более быстрой и последовательной.
Причина, по которой итерация LinkedHashMap быстрее, чем итерация HashMap, заключается в том, что итерация HashMap должна перебирать все ведра, даже пустые. Тот факт, что LinkedHashMap имеет список, указывающий на данные, означает, что он может пропускать пустые ведра. Список в LinkedHashMap является связанным списком, потому что время удаления остается постоянным (а не O (n), если это был список с резервным копированием).
Ответ 2
Связанные списки времени выполнения итераций (доступ к каждому элементу) являются "теоретически" такими же, как список массивов. Оба требуют O (n) (Big-O Notation). Однако, поскольку выделение памяти для массивов осуществляется над непрерывным блоком памяти (элементы связанных списков выделяются индивидуально и могут быть где угодно в памяти), кэширование вступает в силу.
Ответ 3
Некоторые сведения:
Порядок итератора для LinkedHashMap совпадает с порядком размещения на карте. Таким образом, часть LinkedList должна "вставлять" в конец (что является O (1) для связанного списка, который отслеживает хвост), а часть карты имеет только вставку карты, которая является O (1). Общая вставка связанного списка - это O (N), а вставка ArrayList должна копировать содержимое в 1 слот до того, как может произойти вставка.
Ответ 4
Чтобы перебрать связанный список, нужно следить за каждой ссылкой (ссылкой) в каждом элементе. Эти ссылки могут указывать почти где угодно, нет гарантии, что следующий элемент следует за текущим в памяти, что плохо для кэширования. Поскольку каждая ссылка должна быть восстановлена, она медленнее.
Массивы непрерывны в памяти, а следующий элемент - это только ячейка памяти текущего элемента, увеличенная с размером элемента.
Для двусвязного списка вставка в любом месте массива выполняется очень быстро, потому что необходимо изменить только ссылки предыдущего и следующего элементов. С другой стороны, массив работает медленнее, поскольку вставка в любой точке приведет к копированию всего массива, чтобы создать пространство для нового элемента. Даже добавление элемента также приведет к копированию всего массива, если для массива недостаточно добавленной непрерывной памяти и добавленного элемента.
Вы особенно заметите различия при вставке при работе с большими наборами данных. Независимо от того, насколько быстр arraycopy()
мог быть, дважды связанный список всегда быстрее для вставки. Поскольку HashMaps редко повторяются и полагаются на вставку и порядок, двойной список может дать ему повышение производительности.