Java HashMap-это необходимо использовать.put () для каждого набора? [дубликат]

этот вопрос уже есть ответ здесь:

представьте себе следующую ситуацию. У вас есть набор значений, которые уже доступны и известны. Вы должны поместить их в HashMap по причинам.

код пример:

String a = "a";
Strinb b = "b";
...
HashMap map = new HashMap(5);
map.put("a", a);
map.put("b", b);
...

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

Я говорю о чем-то вроде этого:

HashMap map = new HashMap(<"a", a>, <"b", b>, ...);

или даже что-то вроде этого:

HashMap map = new HashMap(5);
HashMap.putBunchOfStuff("a", a, "b", b, ...);

редактировать: я собирался спросить, если есть способ но главное, если ответ "Нет", почему нет такого конструктора/метода.

4 ответов


к сожалению, коллекция литералы были предложение по проекту Coin в Java 7 (и Java 8), но он никогда не попадал в конечный продукт, он же не является особенностью Java.

предложение было такое

Here’s how it would look with map literals:


    final Map<Integer, String> platonicSolids = { 
          4 : "tetrahedron",
          6 : "cube", 
          8 : "octahedron", 
          12 : "dodecahedron", 
          20 : "icosahedron"
    };


Here is the empty map literal, which has a slightly irregular syntax to make
it differ from the empty set:


    Map<String, Integer> noJokeHere = { : };

но этого никогда не было, так что, к сожалению, это не работает. Так что, если вы не напишете свой собственный волшебный строитель или фантазии лямбда, как на этом сайте Per-Åke Minborg, ты на твой собственный. Однако следующее с сайта должно работать (в Java 8).

//copy paste from linked site
Map<Integer, String> map = Stream.of(
            new SimpleEntry<>(0, "zero"),
            new SimpleEntry<>(1, "one"),
            //...
            new SimpleEntry<>(11, "eleven"),
            new SimpleEntry<>(12, "twelve"))
            .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue()));

и упрощенная версия, также из сайт:

//copy paste from linked site
public static <K, V> Map.Entry<K, V> entry(K key, V value) {
    return new AbstractMap.SimpleEntry<>(key, value);
}

public static <K, U> Collector<Map.Entry<K, U>, ?, Map<K, U>> entriesToMap() {
    return Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue());
}

Map<Integer, String> map = Stream.of(
            entry(0, "zero"),
            //...
            entry(12, "twelve"))
            .collect(entriesToMap());

литералы коллекции не были введены из-за эти пункты:

  • "простая" версия этой функции (только наборы, списки, карты) не является очень удовлетворительный или популярный; "расширяемая" версия этой функции открытый, грязный и практически гарантированный путь overrun свой дизайн бюджет;

  • версия на основе библиотеки дает нам X% преимущества для 1% стоимость, где X >> 1;

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

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

Брайан Гетц из Oracle


по умолчанию нет такого конструктора - вы можете использовать идиому двойной скобки для put все значения в карте при создании экземпляра, но для этого все еще требуется несколько вызовов put:

Map<String,String> map = new HashMap<>() {{
    put("a", "val1");
    put("b", "val2");
    //etc.
}};

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

у гуавы есть putAll() на ImmutableMap.Builder, позволяя вам сделать что - то подобное к этому до создания экземпляра. Другие внешние библиотеки могут иметь другое подобное поведение, но на самом деле вам придется прибегать к использованию внешних библиотек.


можно создать довольно полезный метод для создания карт с помощью varargs.

пример:

@SuppressWarnings("unchecked")
public static <K, V> HashMap<K, V> newMap(Object... elems) {
    HashMap<K, V> m = new HashMap<K, V>();

    for (int i = 0; i < elems.length; i += 2) {
        m.put((K) elems[i], (V) elems[i + 1]);    
    }

    return m;
}

Map<String, Integer> m = newMap("k1", 1, "k2", 2);        

внимание: это не тип safe и может привести к карте с объектами неправильных типов, если вы сделаете ошибку при ее использовании, бросая ClassCastException в неожиданных местах. Это называется загрязнение "кучи". Пример:

Map<String, Integer> m = newMap("k1", 1, "k2", "2");
int s = m.get("k2");  // ClassCastException!

вы можете использовать что-то вроде этого :

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

но я не знаю, можно ли использовать u с локальной переменной a и b.