Выстраиваются ли ключи и значения в неупорядоченной хэш-карте при независимой итерации? - PullRequest
0 голосов
/ 18 февраля 2019

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

Вот краткий фрагмент для пояснения:

public class App {
    public static void main(String[] args) {
        Map<String,String> stateCapitols = new HashMap<>();
        stateCapitols.put("AL", "Montgomery");
        stateCapitols.put("AK", "Juneau");
        stateCapitols.put("CO", "Denver");
        stateCapitols.put("FL", "Tallahassee");
        stateCapitols.put("Indiana", "Indianapolis");

        stateCapitols.keySet().stream().forEach(System.out::println);
        System.out.println();
        stateCapitols.values().stream().forEach(System.out::println);
    }
}

Может ли AL появиться в том же месте, что и Denver (или любое другое значение) в приведенном выше примере?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

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

Это указано в спецификации HashMap :

Этот класс не дает никаких гарантий относительно порядкакарты;в частности, это не гарантирует, что порядок останется постоянным во времени.

На практике порядок итераций HashMap стабилен от одной итерации к следующей, и дажеот одного вызова JVM к другому, если HashMap инициализируется и заполняется точно так же.Однако для приложения неразумно полагаться на это.Создание HashMap с другим начальным размером или коэффициентом загрузки может повлиять на порядок итераций, даже если карта заполнена тем же содержимым.Реализация HashMap время от времени меняется, и это также влияет на порядок итераций.Такие изменения происходят даже в выпусках исправлений или исправлений JDK.К сожалению, история показала, что приложения ломаются при изменении порядка итераций.Поэтому надежные приложения должны стремиться избегать каких-либо зависимостей от порядка итерации HashMap.

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

Если вам нужно сопоставить ключи и значения HashMap во время его итерации, получите entrySet () HashMap и повторите это.Он предоставляет записи карты (пары ключ-значение), поэтому связь между ключами и значениями сохраняется.

Альтернативные реализации Map в JDK обеспечивают четко определенный порядок итераций.TreeMap и ConcurrentSkipListMap упорядочивают свои записи на основе предоставленного метода сравнения.LinkedHashMap обеспечивает порядок итераций, основанный на порядке вставки.(Он также предоставляет режим, в котором итерация выполняется по порядку доступа, что иногда полезно, но поведение которого часто удивляет.)

Обратите внимание, что немодифицируемые коллекции введены в Java 9 (Set.of, Map.of,и т.д.) обеспечивает рандомизированный порядок итераций.Порядок будет отличаться от одного запуска JVM к другому.Это должно помочь приложениям избежать непреднамеренных зависимостей от порядка итерации.

0 голосов
/ 19 февраля 2019

Давайте еще раз посмотрим на язык API Java SE, касающийся порядка итераций в контракте Map:

Некоторые реализации карт, такие как класс TreeMap, дают конкретные гарантии в видепо их заказу;другие, такие как класс HashMap, этого не делают.

И HashMap:

Этот класс не дает никаких гарантий относительно порядкакарта;в частности, это не гарантирует, что порядок останется постоянным с течением времени.

Поскольку явно указано, что итераторы HashMap не имеют порядка, нельзя предполагать, что итерация будет стабильной даже между вызовами одного и того же метода , не говоря уже овызовы различных методов keySet() и values().

Полезно, Map имеет метод entrySet(), который делает именно то, что вам нужно: онперебирает содержимое карты таким способом, который объединяет ключи и значения.Это метод, который можно использовать в любое время, когда вам нужно полагаться на обе части пары.

С изменениями в лицензировании Java, вступающими в силу, люди и организации, которые предполагали, что, вероятно, всегда будут использовать реализацию Java от Oracle,сейчас ищу альтернативные реализации.Полагаться на неписаные подробности об одной реализации крайне опасно, даже сейчас, когда изменения в лицензировании и ценах Oracle изменились.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...