Порядок Hashtable.keySet()?

Недавно я изучал Java, и у меня есть вопрос.

Я узнал, что HashMap и Hashtable не сохраняют порядок вставки или порядок, основанный на ключе. Но я столкнулся с ситуацией, когда этого не происходит.

import java.util.HashMap;
import java.util.Hashtable;

public class Main {
    public static void main(String[] args) {

        Hashtable<Integer, Integer> hashtableInt = new Hashtable<>();
        Hashtable<String, Integer> hashtableStr = new Hashtable<>();
        HashMap<Integer, Integer> hashMapInt = new HashMap<>();
        HashMap<String, Integer> hashMapStr = new HashMap<>();

        for (int i = 0; i < 25; i++) {
            hashtableInt.put(i, i);
            hashtableStr.put(String.valueOf(i), i);
            hashMapInt.put(i, i);
            hashMapStr.put(String.valueOf(i), i);
        }

        System.out.println("Hashtable with Integer keys : ");
        for (int key : hashtableInt.keySet())   System.out.print(key + " ");

        System.out.println("\n\nHashtable with String keys : ");
        for (String key : hashtableStr.keySet())   System.out.print(key + " ");

        System.out.println("\n\nHashMap with Integer keys : ");
        for (int key : hashMapInt.keySet())   System.out.print(key + " ");

        System.out.println("\n\nHashMap with String keys : ");
        for (String key : hashMapStr.keySet())   System.out.print(key + " ");
    }
}
Hashtable with Integer keys : 
24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 

Hashtable with String keys : 
19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 24 3 23 2 22 1 21 0 20 

HashMap with Integer keys : 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 

HashMap with String keys : 
22 23 24 10 11 12 13 14 15 16 17 18 19 0 1 2 3 4 5 6 7 8 9 20 21 %                                     

В приведенном выше выводе хеши, использующие ключи Integer, имеют определенный порядок. Только хеши, принимающие String в качестве ключа, не имеют порядка. Кроме того, порядок клавиш между Hashtable и HashMap с клавишами Integer различен.

Итак, что я хочу знать, так это...

  1. Почему Hashtable().keySet() и HashMap().keySet() имеют порядок? Обычно хеши и наборы не имеют определенного порядка. Почему это? Я что-то пропустил?

  2. Почему Hashtable().keySet() и HashMap().keySet() имеют противоположный порядок? В конце концов, эти два будут хешем, но что-то внутри работает по-другому?

  3. Если ожидается, что keySet() будет иметь порядок, то почему Hashtable().keySet() и HashMap().keySet() имеют неправильный порядок?

Спасибо вам всем.

Я отладил метод put() и посмотрел, как он работает, но для меня это слишком сложно.

«Идеальный порядок» в хеш-таблице — это всего лишь случайность и зависит как от того, как хеш-таблица хранит ключи в своей внутренней структуре данных, так и от способа расчета хэш-кода для каждого типа ключа. Для получения дополнительной информации я предлагаю вам изучить методы hashCode() для строк и целых чисел, а также способ реализации хэш-таблиц в целом.

Torben 09.04.2024 13:58

Также учтите, что для такого рода неупорядоченных коллекций (в данном случае Set) определенный порядок не гарантируется (из документации Set: «Порядок итерации элементов набора не указан и может быть изменен.»). Это не означает, что гарантировано, что порядок не будет поддерживаться. Просто на порядок нельзя полагаться.

Federico klez Culloca 09.04.2024 14:15

попробуйте заполнить карту более крупными числами, например 500 - 525 ...

user85421 09.04.2024 16:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

На порядок полагаться нельзя. Хотя на самом деле это происходит не случайно, можно определенно считать это случайностью. Java просто предоставляет вам элементы в том порядке, в котором они хранятся.
Если вам нужен Map с указанным порядком встречи. См. также SequencedMap для этого.

Это связано с тем, как структуры хэш-данных хранят данные. Они основаны на распределении данных по нескольким сегментам (обычно сегментов больше, чем точек данных). Чтобы решить, какая точка данных попадает в какую корзину, он вызывает метод hashCode объекта, а затем использует операции с модулем для распределения ее по корзинам. В случае Integer это возвращает вам исходный номер.

Таким образом, если у вас есть 10 сегментов и вы храните в них числа 1,2,3,4,5,5,6, число 1 перейдет в сегмент 1, а число 2 — в сегмент 2 и т. д. Однако, если вы, например, если номера разбросаны больше (или начинаются с другого номера), это больше не будет работать.

Например, если мы сохраним числа 10, 20 и 30 в HashMap, порядок больше не будет работать:

HashMap<Integer, Integer> hashMapInt = new HashMap<>();
hashMapInt.put(10, 10);
hashMapInt.put(20, 20);
hashMapInt.put(30, 30);
for (int key : hashMapInt.keySet())   System.out.print(key + " ");

В моей системе этот код приводит к выводу 20 10 30.

При хранении элементов в виде String с каждым элементом связано больше данных, а метод hashCode объединяет разные символы/байты, поэтому два String, представляющие последовательные числа, имеют более разбросанные хеши.

Порядок элементов в HashMap или Hashtable не указан и может даже различаться в разных JVM.

Две вещи. Во-первых, вам не следует использовать HashTable — это устаревшая коллекция, которая не используется современными программами Java.

Во-вторых, никогда не пишите программное обеспечение, которое ожидает определенного порядка ключей в HashMap. Если вам нужен порядок, отсортируйте ключи. Но полагаться на порядок из любого хеш-контейнера — это верный путь к появлению ошибок в программном обеспечении, поскольку этот порядок должен быть изменен, не затрагивая ваш код.

Просто верьте, что HashMap знает, что делает.

Другие вопросы по теме