Есть ли способ инициализации Java HashMap, как это ?:
Map<String,String> test =
new HashMap<String, String>{"test":"test","test":"test"};
Какой будет правильный синтаксис? Я не нашел ничего относительно этого. Это возможно? Я ищу самый короткий / быстрый способ поместить некоторые «окончательные / статические» значения в карту, которые никогда не меняются и известны заранее при создании карты.
Ответы:
Все версии
На случай, если вам понадобится всего одна запись: есть
Collections.singletonMap("key", "value")
.Для Java версии 9 или выше:
Да, это возможно сейчас. В Java 9 было добавлено несколько заводских методов, которые упрощают создание карт:
В приведенном выше примере оба
test
иtest2
будут одинаковыми, только с разными способами выражения карты.Map.of
Метод определен до десяти элементов в карте, в то время какMap.ofEntries
метод не будет иметь такой предел.Обратите внимание, что в этом случае полученная карта будет неизменной. Если вы хотите, чтобы карта была изменчивой, вы можете скопировать ее снова, например, используя
mutableMap = new HashMap<>(Map.of("a", "b"));
(См. Также JEP 269 и Javadoc )
До версии Java 8:
Нет, вам придется добавить все элементы вручную. Вы можете использовать инициализатор в анонимном подклассе, чтобы сделать синтаксис немного короче:
Однако в некоторых случаях анонимный подкласс может привести к нежелательному поведению. Это включает в себя, например:
Использование функции для инициализации также позволит вам создать карту в инициализаторе, но позволит избежать неприятных побочных эффектов:
источник
Collections.singletonMap()
:)entry
документирована Java 9 ?Это один из способов.
Тем не менее, вы должны быть осторожны и убедитесь, что вы понимаете приведенный выше код (он создает новый класс, который наследуется от HashMap). Поэтому вы должны прочитать больше здесь: http://www.c2.com/cgi/wiki?DoubleBraceInitialization или просто использовать Guava:
источник
Если вы разрешаете сторонним библиотекам, вы можете использовать Gumm 's ImmutableMap для достижения краткости, подобной буквальной:
Это работает до 5 пар ключ / значение , в противном случае вы можете использовать его конструктор :
источник
Нет прямого способа сделать это - у Java нет литералов Map (пока - я думаю, что они были предложены для Java 8).
Некоторым людям нравится это:
Это создает анонимный подкласс HashMap, инициализатор которого помещает эти значения. (Кстати, карта не может содержать дважды одинаковое значение, ваш второй пут будет перезаписывать первый. Я буду использовать другие значения в следующих примерах.)
Нормальный способ будет таким (для локальной переменной):
Если ваша
test
карта является переменной экземпляра, поместите инициализацию в конструктор или инициализатор экземпляра:Если ваша
test
карта является переменной класса, поместите инициализацию в статический инициализатор:Если вы хотите, чтобы ваша карта никогда не менялась, вы должны после инициализации обернуть вашу карту
Collections.unmodifiableMap(...)
. Вы также можете сделать это в статическом инициализаторе:(Я не уверен, что теперь вы можете сделать
test
финал ... попробуйте и сообщите здесь.)источник
источник
HashMap
этого подкласса. Это может работать, только если вы на самом деле их предоставили. (С новым (пустым) HashMap аргументы типа не имеют значения.)Альтернатива, используя простые классы Java 7 и varargs: создайте класс
HashMapBuilder
с этим методом:Используйте метод как это:
источник
ТЛ; др
Используйте
Map.of…
методы в Java 9 и позже.Map.of
Java 9 добавила серию
Map.of
статических методов, чтобы сделать то, что вы хотите: создать неизменяемоеMap
с использованием буквального синтаксиса .Карта (коллекция записей) является неизменной, поэтому вы не можете добавлять или удалять записи после создания экземпляра. Кроме того, ключ и значение каждой записи являются неизменяемыми, не могут быть изменены. См. Javadoc для других правил, таких как недопустимые значения NULL, дубликаты ключей не допускаются, и порядок итераций сопоставлений является произвольным.
Давайте посмотрим на эти методы, используя некоторые примерные данные для карты дня недели для человека, который, как мы ожидаем, будет работать в этот день.
Map.of()
Map.of
создает пустойMap
. Не изменяется, поэтому вы не можете добавлять записи. Вот пример такой карты, пустой, без записей.Map.of( … )
Map.of( k , v , k , v , …)
Есть несколько методов, которые принимают от 1 до 10 пар ключ-значение. Вот пример двух записей.Map.ofEntries( … )
Map.ofEntries( Map.Entry , … )
принимает любое количество объектов, реализующихMap.Entry
интерфейс. Java объединяет два класса, реализующих этот интерфейс, один изменяемый, другой неизменный:AbstractMap.SimpleEntry
,AbstractMap.SimpleImmutableEntry
. Но нам не нужно указывать конкретный класс. Нам просто нужно вызватьMap.entry( k , v )
метод, передать наш ключ и наше значение, и мы вернем объект некоторогоMap.Entry
интерфейса, реализующего класс .Map.copyOf
Java 10 добавил метод
Map.copyOf
. Передайте существующую карту, верните неизменную копию этой карты.Ноты
Обратите внимание, что порядок итераторов карт, создаваемых с помощью
Map.of
, не гарантируется. Записи имеют произвольный порядок. Не пишите код в зависимости от увиденного порядка, так как документация предупреждает, что порядок может быть изменен.Обратите внимание , что все эти
Map.of…
методы возвращаютMap
из неопределенного класса . Базовый конкретный класс может даже варьироваться от одной версии Java к другой. Эта анонимность позволяет Java выбирать из различных реализаций, что бы ни подходило для ваших конкретных данных. Например, если ваши ключи взяты из перечисления , Java может использоватьEnumMap
под крышками.источник
Вы можете
Map.of
легко создать свой собственный (который доступен только в Java 9 и выше) двумя простыми способамиСделать это с заданным количеством параметров
пример
Сделать это с помощью списка
Вы также можете сделать это, используя список, вместо того, чтобы создавать множество методов для определенного набора параметров.
пример
Примечание. Не рекомендуется использовать это для всего, так как это делает анонимный класс каждый раз, когда вы используете это.
источник
JAVA 8
В простой Java 8 у вас также есть возможность использовать
Streams/Collectors
для выполнения этой работы.Это имеет преимущество в том, что не создает анонимный класс.
Обратите внимание, что импорт:
Конечно, как отмечалось в других ответах, в java 9 и далее у вас есть более простые способы сделать то же самое.
источник
К сожалению, использование varargs, если тип ключей и значений не совпадает, не очень разумно, так как вам придется полностью использовать
Object...
безопасность типов. Если вы всегда хотите создать, например, aMap<String, String>
, то , конечно,toMap(String... args)
было бы возможно a , но не очень красиво, так как было бы легко смешивать ключи и значения, и нечетное количество аргументов было бы недопустимым.Вы можете создать подкласс HashMap, который имеет цепочечный метод, такой как
и использовать его как
new ChainableMap<String, Object>().set("a", 1).set("b", "foo")
Другой подход заключается в использовании общего шаблона компоновщика:
и использовать его как
new MapBuilder<String, Object>().put("a", 1).put("b", "foo").build();
Тем не менее, решение, которое я использовал время от времени, использует varargs и
Pair
класс:Map<String, Object> map = Maps.of(Pair.create("a", 1), Pair.create("b", "foo");
Многословие
Pair.create()
меня немного беспокоит, но это работает вполне нормально. Если вы не возражаете против статического импорта, вы, конечно, можете создать помощника:Map<String, Object> map = Maps.of(p("a", 1), p("b", "foo");
(Вместо этого
Pair
можно представить себе использованиеMap.Entry
, но, поскольку это интерфейс, он требует реализации класса и / или вспомогательного метода фабрики. Он также не является неизменным и содержит другую логику, не полезную для этой задачи.)источник
Вы можете использовать потоки в Java 8 (это пример Set):
Ссылка: https://www.baeldung.com/java-double-brace-initialization
источник
Если вам нужно разместить только одну пару ключ-значение, вы можете использовать Collections.singletonMap (key, value);
источник