додавання декількох записів до HashMap одночасно в одному операторі


138

Мені потрібно ініціалізувати постійний HashMap, і я хотів би це зробити в одному рядковому операторі. Уникаючи подібного:

  hashMap.put("One", new Integer(1)); // adding value into HashMap
  hashMap.put("Two", new Integer(2));      
  hashMap.put("Three", new Integer(3));

подібний до цього в об'єкті C:

[NSDictionary dictionaryWithObjectsAndKeys:
@"w",[NSNumber numberWithInt:1],
@"K",[NSNumber numberWithInt:2],
@"e",[NSNumber numberWithInt:4],
@"z",[NSNumber numberWithInt:5],
@"l",[NSNumber numberWithInt:6],
nil] 

Я не знайшов жодного прикладу, який би показував, як це зробити, переглянувши так багато.

Відповіді:


258

Ви можете зробити це:

Map<String, Integer> hashMap = new HashMap<String, Integer>()
{{
     put("One", 1);
     put("Two", 2);
     put("Three", 3);
}};

11
@ user387184 Так, вони називають це "ініціалізатор подвійної дужки". Дивіться цю тему: stackoverflow.com/questions/924285 / ...
Eng.Fouad

2
Я просто вкладаю його у свій код і отримую це попередження / повідомлення у рядку: "Клас" серіалізація "не оголошує статичне остаточне поле serialVersionUID типу". Чи можу я просто проігнорувати це? що це означає? Дякую
користувач387184

31
Не слід використовувати цей метод. Він створює новий клас кожного разу, коли ви його використовуєте, що має набагато гірші показники, ніж просто просте створення карти. Див stackoverflow.com/questions/924285 / ...
Timo Türschmann

7
Причина, яку я спростував, це тому, що вона не пояснила, що це створює новий клас кожного разу, коли ви ним користуєтесь. Я думаю, що люди повинні бути обізнані про компромісні дії цього.
idungotnosn

6
@ TimoTürschmann Здається, що якщо мені колись знадобиться статична ініціалізація такої карти, що вона також буде статичною, виключаючи кожен раз, коли ви використовуєте її покарання за продуктивність - ви будете мати це покарання один раз. Я не бачу іншого разу, щоб хтось захотів такого типу ініціалізації, без того, щоб змінна була статичною (наприклад, хтось коли-небудь використовувати це в циклі?). Я можу помилятися, хоча програмісти винахідливі.
Кріс Сірефіс

65

Ви можете використовувати ImmutableMap Google Guava. Це працює, якщо ви не піклуєтесь про те, щоб потім змінити карту (ви не можете зателефонувати .put () на карту після її створення за допомогою цього методу):

import com.google.common.collect.ImmutableMap;

// For up to five entries, use .of()
Map<String, Integer> littleMap = ImmutableMap.of(
    "One", Integer.valueOf(1),
    "Two", Integer.valueOf(2),
    "Three", Integer.valueOf(3)
);

// For more than five entries, use .builder()
Map<String, Integer> bigMap = ImmutableMap.<String, Integer>builder()
    .put("One", Integer.valueOf(1))
    .put("Two", Integer.valueOf(2))
    .put("Three", Integer.valueOf(3))
    .put("Four", Integer.valueOf(4))
    .put("Five", Integer.valueOf(5))
    .put("Six", Integer.valueOf(6))
    .build();

Дивіться також: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableMap.html

Дещо пов’язане питання: ImmutableMap.of () вирішення для HashMap у Картах?


Гуава величезна, я б не використовував її для свого додатка для Android, якщо це абсолютно не потрібно
ericn

4
Слідкуйте за тим, щоб ImmutableMapне приймати nullключі чи значення.
Вадзім

@ericn ProGuard дозволяє виключати будь-які частини бібліотеки, які ви не використовуєте.
dimo414

55

Оскільки Java 9, можна використовувати Map.of(...)так:

Map<String, Integer> immutableMap = Map.of("One", 1, 
                                           "Two", 2, 
                                           "Three", 3);

Ця карта незмінна. Якщо ви хочете, щоб карта була змінною, ви повинні додати:

Map<String, Integer> hashMap = new HashMap<>(immutableMap);

Якщо ви не можете використовувати Java 9, вам не доводиться писати подібний допоміжний метод самостійно або використовуєте сторонні бібліотеки (наприклад, Guava ), щоб додати цю функціональність для вас.


Після додавання 10 записів він видає дивну помилку "не може вирішити метод", це помилка з цим методом?
vikramvi

2
@vikramvi так Якщо ви подивитеся на документацію Map.of робиться лише до 10 записів, оскільки це досить трудомістко
jolivier

8

У Java немає буквальної карти, тому немає жодного приємного способу зробити саме те, що ви просите.

Якщо вам потрібен такий тип синтаксису, розгляньте кілька Groovy, який сумісний з Java і дозволяє:

def map = [name:"Gromit", likes:"cheese", id:1234]

8

На Картах також були додані фабричні методи на Java 9. Для до 10 записів Карти перевантажують конструктори, які беруть пари ключів і значень. Наприклад, ми могли б скласти карту різних міст та їх населення (за даними Google у жовтні 2016 року) таким чином:

Map<String, Integer> cities = Map.of("Brussels", 1_139000, "Cardiff", 341_000);

Випадок var-args для Map трохи складніше, вам потрібно мати і ключі, і значення, але в Java методи не можуть мати двох параметрів var-args. Таким чином, загальний випадок обробляється методом Map.Entry<K, V>об'єктів var-args та додаванням статичного entry()методу, який їх конструює. Наприклад:

Map<String, Integer> cities = Map.ofEntries(
    entry("Brussels", 1139000), 
    entry("Cardiff", 341000)
);

Колекційні фабричні методи на Java 9


Чудово, якщо ви могли використовувати Java 9+. Також цей заводський метод повертає непорушну карту.
Сурабх

6

Ось простий клас, який здійснить те, що ви хочете

import java.util.HashMap;

public class QuickHash extends HashMap<String,String> {
    public QuickHash(String...KeyValuePairs) {
        super(KeyValuePairs.length/2);
        for(int i=0;i<KeyValuePairs.length;i+=2)
            put(KeyValuePairs[i], KeyValuePairs[i+1]);
    }
}

А потім використовувати його

Map<String, String> Foo=QuickHash(
    "a", "1",
    "b", "2"
);

Це дає {a:1, b:2}


4
    boolean x;
    for (x = false, 
        map.put("One", new Integer(1)), 
        map.put("Two", new Integer(2)),      
        map.put("Three", new Integer(3)); x;);

Ігноруючи декларацію x(що необхідно, щоб уникнути діагностики "недосяжного твердження"), технічно це лише одне твердження.


14
Це огидно хакі.
Сходи

1
@MicahStairs - Але це лише одне твердження.
Гарячі лизання

2
Щоправда, але це такий код, який я ніколи не сподіваюся натрапити на виробництво.
Сходи

@MicahStairs - я бачив і гірше.
Гарячі лизання

1
Omg Я шукав це сьогодні, як працює цей код? Я додав його в код для тестування, але я не можу зрозуміти, як це працює всередині ... :)
GOXR3PLUS

1

Ви можете додати цю функцію утиліти до класу утиліти:

public static <K, V> Map<K, V> mapOf(Object... keyValues) {
    Map<K, V> map = new HashMap<>();

    for (int index = 0; index < keyValues.length / 2; index++) {
        map.put((K)keyValues[index * 2], (V)keyValues[index * 2 + 1]);
    }

    return map;
}

Map<Integer, String> map1 = YourClass.mapOf(1, "value1", 2, "value2");
Map<String, String> map2 = YourClass.mapOf("key1", "value1", "key2", "value2");

Примітка: у Java 9вас можна використовувати Map.of


-1

Іншим підходом може бути написання спеціальної функції для отримання всіх значень елементів з одного рядка регулярним виразом:

import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Example {
    public static void main (String[] args){
        HashMap<String,Integer> hashMapStringInteger = createHashMapStringIntegerInOneStat("'one' => '1', 'two' => '2' , 'three'=>'3'  ");

        System.out.println(hashMapStringInteger); // {one=1, two=2, three=3}
    }

    private static HashMap<String, Integer> createHashMapStringIntegerInOneStat(String str) {
        HashMap<String, Integer> returnVar = new HashMap<String, Integer>();

        String currentStr = str;
        Pattern pattern1 = Pattern.compile("^\\s*'([^']*)'\\s*=\\s*>\\s*'([^']*)'\\s*,?\\s*(.*)$");

        // Parse all elements in the given string.
        boolean thereIsMore = true;
        while (thereIsMore){
            Matcher matcher = pattern1.matcher(currentStr);
            if (matcher.find()) {
                returnVar.put(matcher.group(1),Integer.valueOf(matcher.group(2)));
                currentStr = matcher.group(3);
            }
            else{
                thereIsMore = false;
            }
        }

        // Validate that all elements in the given string were parsed properly
        if (currentStr.length() > 0){
            System.out.println("WARNING: Problematic string format. given String: " + str);
        }

        return returnVar;
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.