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

869

Есть ли способ инициализации Java HashMap, как это?:

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

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

Показать ещё 4 комментария
Теги:
dictionary
collections
initialization
map

6 ответов

1034
Лучший ответ

Для 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:
Map<String, String> test2 = Map.ofEntries(
    entry("a", "b"),
    entry("c", "d")
);

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

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

(См. Также JEP 269 и Javadoc)

До версии Java 8:

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

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

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

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

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;
}
  • 3
    Это не сработает, если вы хотите инициализировать элементы в функции ...
  • 9
    @ Майкл: Да, если вы хотите использовать функцию, вы не можете использовать не-функцию. Но почему ты хочешь?
Показать ещё 9 комментариев
917

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

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

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

Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
  • 68
    Это работает, но уродливо и имеет невидимые побочные эффекты, которые пользователь должен понять, прежде чем делать это - например, создание целого анонимного класса на месте.
  • 85
    да, именно так я и написал о том, чтобы быть осторожным, и дал ссылку на описание.
Показать ещё 10 комментариев
287

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

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();


  • обратите внимание, что реализация Guava ImmutableMap отличается от реализации Java HashMap (в частности, она неизменна и не допускает нулевые ключи/значения)
  • Для получения дополнительной информации см. статью руководства Guava о ее неизменных типах коллекций.
  • 25
    Кроме того, в guava есть ImmutableMap.builder.put ("k1", "v1"). Put ("k2", "v2"). Build ();
  • 15
    ImmutableMap - это не то же самое, что HashMap, поскольку он потерпит неудачу при нулевых значениях, тогда как map HashMap - нет.
Показать ещё 2 комментария
99

Нет прямого способа сделать это - у Java нет литералов в Карте (но я думаю, что они были предложены для 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... попробовать и сообщить здесь.)

56
Map<String,String> test = new HashMap<String, String>()
{
    {
        put(key1, value1);
        put(key2, value2);
    }
};
  • 0
    Просто и по существу. Я думаю, что это с расширенным разделом комментариев будет лучшим ответом.
  • 0
    Почему у этого нет больше голосов? Разве это не лучше, чем другие ответы? Я выгляжу намного чище. Может кто-нибудь объяснить мне, пожалуйста? Потому что я мог бы использовать это. Благодарю.
Показать ещё 5 комментариев
44

Альтернатива, используя простые классы Java 7 и varargs: создайте класс HashMapBuilder с помощью этого метода:   

public static HashMap<String, String> build(String... data){
    HashMap<String, String> result = new HashMap<String, String>();

    if(data.length % 2 != 0) 
        throw new IllegalArgumentException("Odd number of arguments");      

    String key = null;
    Integer step = -1;

    for(String value : data){
        step++;
        switch(step % 2){
        case 0: 
            if(value == null)
                throw new IllegalArgumentException("Null key value"); 
            key = value;
            continue;
        case 1:             
            result.put(key, value);
            break;
        }
    }

    return result;
}

Используйте метод следующим образом:

HashMap<String,String> data = HashMapBuilder.build("key1","value1","key2","value2");
  • 0
    Я написал ответ, вдохновленный твоим: stackoverflow.com/questions/507602/…
  • 0
    Другое решение с Apache Utils, которое никогда не упоминается, но доступно для чтения, используя предыдущие версии Java: MapUtils.putAll (new HashMap <String, String> (), new Object [] {"Мой ключ", "мое значение", ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню