Вопрос-ответ

How to directly initialize a HashMap (in a literal way)?

Как напрямую инициализировать HashMap (буквальным способом)?

Есть ли какой-нибудь способ инициализации Java HashMap подобным образом?:

Map<String,String> test = 
new HashMap<String, String>{"test":"test","test":"test"};

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

Переведено автоматически
Ответ 1

Все версии

На случай, если вам понадобится всего одна запись: есть Collections.singletonMap("key", "value").

Для Java версии 9 или выше:

Да, теперь это возможно. В Java 9 добавлена пара заводских методов, упрощающих создание карт :

// this works for up to 10 elements:
Map<String, String> test1 = Map.of(
"a", "b",
"c", "d"
);

// this works for any number of elements:
import static java.util.Map.entry;
Map<String, String> test2 = Map.ofEntries(
entry("a", "b"),
entry("c", "d")
);

В приведенном выше примере оба test и test2 будут одинаковыми, просто с разными способами выражения Map. Map.of Метод определен максимум для десяти элементов карты, в то время как у Map.ofEntries метода такого ограничения не будет.

Обратите внимание, что в этом случае результирующая карта будет неизменяемой картой. Если вы хотите, чтобы карта была изменяемой, вы можете скопировать ее снова, например, используя mutableMap = new HashMap<>(Map.of("a", "b"));. Также обратите внимание , что в этом случае ключи и значения не должны быть null.

(Смотрите также JEP 269 и Javadoc)

Для Java версии до 8:

Нет, вам придется добавлять все элементы вручную. Вы можете использовать инициализатор в анонимном подклассе, чтобы немного сократить синтаксис:

Map<String, String> myMap = new HashMap<String, String>() {{
put("a", "b");
put("c", "d");
}};

Однако анонимный подкласс в некоторых случаях может приводить к нежелательному поведению. Это включает, например:


  • Он генерирует дополнительный класс, который увеличивает потребление памяти, дискового пространства и время запуска

  • В случае нестатического метода: Он содержит ссылку на объект, к которому был вызван метод создания. Это означает, что объект внешнего класса не может быть собран мусором, пока на созданный объект map все еще ссылаются, тем самым блокируя дополнительную память

Использование функции для инициализации также позволит вам сгенерировать карту в инициализаторе, но позволит избежать неприятных побочных эффектов:

Map<String, String> myMap = createMap();

private static Map<String, String> createMap() {
Map<String,String> myMap = new HashMap<String,String>();
myMap.put("a", "b");
myMap.put("c", "d");
return myMap;
}
Ответ 2

Это один из способов.

Map<String, String> h = new HashMap<String, String>() {{
put("a","b");
}};

Однако вам следует быть осторожным и убедиться, что вы понимаете приведенный выше код (он создает новый класс, который наследуется от HashMap). Поэтому вам следует прочитать больше здесь:
http://www.c2.com/cgi/wiki?Двойная трассировка
или просто используйте Guava:

Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);

ImmutableMap.of работает до 5 записей. В противном случае используйте конструктор: исходный код.

Ответ 3

Если вы разрешаете сторонние библиотеки, вы можете использовать ImmutableMap от Guava для достижения краткости, подобной буквальному:

Map<String, String> test = ImmutableMap.of("k1", "v1", "k2", "v2");

Это работает до 5 пар ключ / значение, в противном случае вы можете использовать его конструктор:

Map<String, String> test = ImmutableMap.<String, String>builder()
.put("k1", "v1")
.put("k2", "v2")
...
.build();



  • обратите внимание, что реализация ImmutableMap Guava отличается от реализации HashMap Java (в частности, она неизменяема и не допускает нулевых ключей / значений)

  • для получения дополнительной информации см. Статью руководства пользователя Guava о его неизменяемых типах коллекций

Ответ 4

Прямого способа сделать это нет - по состоянию на 2021 год в Java нет литералов Map (пока - я думаю, они были предложены для Java 8, но не дошли).

Некоторым людям это нравится:

Map<String,String> test = new HashMap<String, String>(){{
put("test","test"); put("test","test");}};

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

Обычный способ был бы таким (для локальной переменной):

Map<String,String> test = new HashMap<String, String>();
test.put("test","test");
test.put("test1","test2");

Если ваша test карта является переменной экземпляра, поместите инициализацию в конструктор или инициализатор экземпляра:

Map<String,String> test = new HashMap<String, String>();
{
test.put("test","test");
test.put("test1","test2");
}

Если ваша test карта является переменной класса, поместите инициализацию в статический инициализатор:

static Map<String,String> test = new HashMap<String, String>();
static {
test.put("test","test");
test.put("test1","test2");
}

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

static Map<String,String> test;
{
Map<String,String> temp = new HashMap<String, String>();
temp.put("test","test");
temp.put("test1","test2");
test = Collections.unmodifiableMap(temp);
}

(Я не уверен, сможете ли вы сейчас сделать test final ... попробуйте и сообщите здесь.)

Начиная с Java 9, у вас также есть синтаксис Map.of(...) и Map.ofEntries(), как описано в ответе от yankee.

java collections