2014-12-06 2 views
0

Моего концептуальное понимания java.util.HashMap выглядит следующим образом:Почему java.util.HashMap использовать связанный список внутри

  1. Ее основной актив по сравнению с другими реализациями Карты является постоянным время поиска, предполагая, что не являются столкновениями. По этой причине базовая реализация использует массив фиксированной длины - единственную структуру данных в информатике, которая имеет O (1) поиск.

  2. Массив фиксированной длины, используемый для хранения записей карты, инициализируется заданным размером при создании и расширении (по расширению, я имею в виду, что создается больший массив и значения, скопированные поперек), когда размер карты приближается к длина массива с фиксированной длиной.

  3. Когда значение помещается в карту, пара значений ключа помещается во внутреннюю связанную реализацию списка для данного ключа. Когда есть столкновение, последующие пары значений ключа добавляются к списку.

  4. При получении с карты hashCode() ключа используется для получения индекса массива реализации внутреннего связанного списка, и вы либо имеете свое значение, если список имеет размер 1, либо вы перебираете по списку вызывая equals() по ключу каждого элемента, пока не найдете свои значения.

Основанный на точке 2, HashMap должен расширять массив, операция, которая, несомненно, линейна. Почему он использует реализацию внутреннего связанного списка (O (n) поиск) для разрешения конфликтов? Почему он не использует структуру данных с поиском O (log n), как двоичное или красное черное дерево, для повышения производительности?

+2

Потому что каждый ожидает, что каждое ведро содержит не более нескольких записей. –

+3

Потому что вы надеетесь получить только очень мало столкновений в первую очередь. Для всего лишь нескольких элементов линейный поиск не является существенным. – 5gon12eder

+1

Если я правильно помню, Java 8 * * возвращается к дереву двоичного поиска, если количество столкновений в одном ковше превышает некоторый порог. –

ответ

3

http://openjdk.java.net/jeps/180

На Java 8, HashMap делает откат к бинарному дереву, если имеется достаточное количество столкновений.

+0

Это сбалансированное двоичное дерево поиска, чтобы быть более конкретным –

2

Хотя он не гарантирует O (1) время вставки, оно имеет амортизировано O (1) время вставки, то есть если вы вставляете большое количество элементов по одному, общее время чтобы их вставить, будет пропорционально количеству вставленных вами элементов.

Это не улучшит это, чтобы изменить структуру данных, используемую для ковшей. Точка расширения массива должна гарантировать, что ожидаемое количество записей в каждом ковше равно константа; это означает, что есть еще постоянная вставка и поиск, даже со связанным списком.

Числа очень тщательно разработаны, с точки зрения расширения и расширения (удвоение размера массива). Это очень похожая техника, используемая в ArrayList, чтобы гарантировать добавление амортизации O (1) в список.

+0

Я не предлагаю улучшать время вставки. Я предлагаю улучшить время поиска для записи в ковше с коллизиями. Поиск одной записи в связанном списке - O (n/2), но существуют структуры данных, такие как некоторые реализации дерева с поиском O (log n).Я думаю, что приведенные выше комментарии прибили его - вы просто не ожидаете достаточных столкновений, чтобы сделать это стоящим. –

+0

@RobertBain Вы сказали, что * Исходя из пункта 2, HashMap не гарантирует время вставки. Развертывание массива, несомненно, является линейным. * Первый абзац - ответ на этот вопрос: он * делает * имеет амортизированное время вставки. Остальное отвечает на ваш главный вопрос: ожидаемое количество записей в ведре постоянное, поэтому поиск по-прежнему остается постоянным. Я правильно ответил на ваш главный вопрос, а также рассмотрел недоразумение в вашем посте. –

+0

Во-первых, спасибо за ваш ответ, я ценю ваше время, но я до сих пор не чувствую, что вполне доволен своим пониманием. Можете ли вы объяснить предложение «Точка расширения массива состоит в том, чтобы гарантировать, что ожидаемое количество записей в каждом ведре является постоянным»? На мой взгляд, точка расширения массива состоит в том, что для ключей есть больше отдельных хеш-значений, чем есть места для размещения значений в HashMap. Я понимаю, что парам значений ключей присваивается индекс массива, основанный на значении hashCode(). Принадлежности Если мне что-то не хватает. –

Смежные вопросы