Jak mogę zainicjować statyczną mapę?

Jak zainicjalizować Statyczne Map w Javie?

Metoda pierwsza: inicjalizacja statyczna
Metoda druga: instance initializer (podklasa anonimowa) lub jakaś inna metoda?

Jakie są plusy i minusy każdego z nich?

Oto przykład ilustrujący dwie metody:

import java.util.HashMap;
import java.util.Map;

public class Test {
    private static final Map<Integer, String> myMap = new HashMap<Integer, String>();
    static {
        myMap.put(1, "one");
        myMap.put(2, "two");
    }

    private static final Map<Integer, String> myMap2 = new HashMap<Integer, String>(){
        {
            put(1, "one");
            put(2, "two");
        }
    };
}
Author: Gerold Broser, 2009-02-03

30 answers

Inicjalizator instancji jest w tym przypadku tylko cukrem składniowym, prawda? Nie rozumiem, po co Ci dodatkowe anonimowe zajęcia, żeby je zainicjować. I nie zadziała, jeśli tworzona klasa będzie ostateczna.

Możesz utworzyć niezmienną mapę używając statycznego inicjalizatora:

public class Test {
    private static final Map<Integer, String> myMap;
    static {
        Map<Integer, String> aMap = ....;
        aMap.put(1, "one");
        aMap.put(2, "two");
        myMap = Collections.unmodifiableMap(aMap);
    }
}
 962
Author: Miserable Variable,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-25 16:06:25

Lubię Guava sposób inicjalizacji statycznej, niezmiennej Mapy:

static final Map<Integer, String> MY_MAP = ImmutableMap.of(
    1, "one",
    2, "two"
);

Jak widać, jest bardzo zwięzły (ze względu na wygodne metody fabryczne w ImmutableMap).

Jeśli chcesz, aby Mapa miała więcej niż 5 wpisów, nie możesz już używać ImmutableMap.of(). Zamiast tego spróbuj ImmutableMap.builder() wzdłuż tych linii:

static final Map<Integer, String> MY_MAP = ImmutableMap.<Integer, String>builder()
    .put(1, "one")
    .put(2, "two")
    // ... 
    .put(15, "fifteen")
    .build();

Aby dowiedzieć się więcej o zaletach niezmiennych narzędzi kolekcji Guava, zobacz Immutable Collections Explained in Guava User Przewodnik .

(podzbiór) guawy kiedyś nazywano zbiorami Google . Jeśli nie używasz tej biblioteki w swoim projekcie Java, to zdecydowanie polecam wypróbowanie jej! Guava szybko stała się jednym z najbardziej popularnych i przydatnych darmowych bibliotek stron trzecich dla Javy, ponieważ[30]}koledzy więc użytkownicy zgadzają się {9]}. (Jeśli jesteś w nim nowy, za tym linkiem kryją się doskonałe zasoby do nauki.)


Update (2015) : co do Java 8, Cóż, I nadal używam podejścia Guava, ponieważ jest o wiele czystsze niż cokolwiek innego. Jeśli nie chcesz zależności od Guava, rozważ zwykłą starą metodę init . Hack z dwuwymiarowe array I Stream API jest dość brzydki, jeśli pytasz mnie, i staje się brzydszy, jeśli trzeba utworzyć mapę, której klucze i wartości nie są tego samego typu(jak Map<Integer, String> w pytaniu).

Jeśli chodzi o przyszłość guawy w ogóle, jeśli chodzi o Javę 8, Louis Wasserman powiedział to W 2014 roku i [update] w 2016 roku ogłoszono, że Guava 21 będzie wymagała i poprawnie obsługiwała Javę 8.

Update (2016) : as Tagir Valeev zwraca uwagę, Java 9 W końcu uczyni to czystym, używając tylko czystego JDK, dodając metody convenience factory dla kolekcji:

static final Map<Integer, String> MY_MAP = Map.of(
    1, "one", 
    2, "two"
);
 379
Author: Jonik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:45

Użyłbym:

public class Test {
    private static final Map<Integer, String> MY_MAP = createMap();

    private static Map<Integer, String> createMap() {
        Map<Integer, String> result = new HashMap<Integer, String>();
        result.put(1, "one");
        result.put(2, "two");
        return Collections.unmodifiableMap(result);
    }
}
  1. unika anonimowych klas, które osobiście uważam za zły styl, i unikać
  2. sprawia, że tworzenie mapy jest bardziej wyraźne
  3. sprawia, że mapa jest niezmodyfikowana
  4. ponieważ MY_MAP jest stała, nazwałbym ją tak jak stała
 162
Author: Peter Štibraný,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-03 21:40:14

Java 5 zapewnia bardziej zwartą składnię:

static final Map<String , String> FLAVORS = new HashMap<String , String>() {{
    put("Up",    "Down");
    put("Charm", "Strange");
    put("Top",   "Bottom");
}};
 158
Author: Chris Noe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-15 21:29:54

Jedną z zalet drugiej metody jest to, że możesz ją zawinąć Collections.unmodifiableMap(), aby zagwarantować, że nic nie zaktualizuje kolekcji później:

private static final Map<Integer, String> CONSTANT_MAP = 
    Collections.unmodifiableMap(new HashMap<Integer, String>() {{ 
        put(1, "one");
        put(2, "two");
    }});

 // later on...

 CONSTANT_MAP.put(3, "three"); // going to throw an exception!
 81
Author: Outlaw Programmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 06:02:08

Oto Java 8 one-line static map initializer:

private static final Map<String, String> EXTENSION_TO_MIMETYPE =
    Arrays.stream(new String[][] {
        { "txt", "text/plain" }, 
        { "html", "text/html" }, 
        { "js", "application/javascript" },
        { "css", "text/css" },
        { "xml", "application/xml" },
        { "png", "image/png" }, 
        { "gif", "image/gif" }, 
        { "jpg", "image/jpeg" },
        { "jpeg", "image/jpeg" }, 
        { "svg", "image/svg+xml" },
    }).collect(Collectors.toMap(kv -> kv[0], kv -> kv[1]));

Edit: aby zainicjować Map<Integer, String> jak w pytaniu, potrzebujesz czegoś takiego:

static final Map<Integer, String> MY_MAP = Arrays.stream(new Object[][]{
        {1, "one"},
        {2, "two"},
}).collect(Collectors.toMap(kv -> (Integer) kv[0], kv -> (String) kv[1]));

Edit(2): istnieje lepsza wersja i_am_zero, która używa strumienia new SimpleEntry<>(k, v) wywołań. Sprawdź tę odpowiedź: https://stackoverflow.com/a/37384773/3950982

 55
Author: Luke Hutchison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-05 23:25:30

W Javie 9:

private static final Map<Integer, String> MY_MAP = Map.of(1, "one", 2, "two");
Zobacz

JEP 269 Po szczegóły. JDK 9 osiągnął ogólną dostępność we wrześniu 2017 roku.

 43
Author: Tagir Valeev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-24 23:11:21

Z kolekcjami Eclipse (dawniej kolekcjami GS) będą działać wszystkie z następujących elementów:

import java.util.Map;

import org.eclipse.collections.api.map.ImmutableMap;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.impl.factory.Maps;

public class StaticMapsTest
{
    private static final Map<Integer, String> MAP =
        Maps.mutable.with(1, "one", 2, "two");

    private static final MutableMap<Integer, String> MUTABLE_MAP =
       Maps.mutable.with(1, "one", 2, "two");


    private static final MutableMap<Integer, String> UNMODIFIABLE_MAP =
        Maps.mutable.with(1, "one", 2, "two").asUnmodifiable();


    private static final MutableMap<Integer, String> SYNCHRONIZED_MAP =
        Maps.mutable.with(1, "one", 2, "two").asSynchronized();


    private static final ImmutableMap<Integer, String> IMMUTABLE_MAP =
        Maps.mutable.with(1, "one", 2, "two").toImmutable();


    private static final ImmutableMap<Integer, String> IMMUTABLE_MAP2 =
        Maps.immutable.with(1, "one", 2, "two");
}

Możesz także statycznie inicjalizować prymitywne mapy za pomocą Kolekcji Eclipse.

import org.eclipse.collections.api.map.primitive.ImmutableIntObjectMap;
import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;
import org.eclipse.collections.impl.factory.primitive.IntObjectMaps;

public class StaticPrimitiveMapsTest
{
    private static final MutableIntObjectMap<String> MUTABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two");

    private static final MutableIntObjectMap<String> UNMODIFIABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .asUnmodifiable();

    private static final MutableIntObjectMap<String> SYNCHRONIZED_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .asSynchronized();

    private static final ImmutableIntObjectMap<String> IMMUTABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .toImmutable();

    private static final ImmutableIntObjectMap<String> IMMUTABLE_INT_OBJ_MAP2 =
            IntObjectMaps.immutable.<String>empty()
                    .newWithKeyValue(1, "one")
                    .newWithKeyValue(2, "two");
} 

Uwaga: jestem committerem Dla Kolekcji Eclipse

 27
Author: Donald Raab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-13 18:47:53

Nigdy nie stworzyłbym anonimowej podklasy w tej sytuacji. Statyczne inicjalizatory działają równie dobrze, jeśli chcesz, aby mapa była niemodyfikowana, na przykład:

private static final Map<Integer, String> MY_MAP;
static
{
    Map<Integer, String>tempMap = new HashMap<Integer, String>();
    tempMap.put(1, "one");
    tempMap.put(2, "two");
    MY_MAP = Collections.unmodifiableMap(tempMap);
}
 24
Author: eljenso,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-04 08:19:39

Jest ODPOWIEDŹ zaproponowana przez Luke ' a, która inicjalizuje mapę za pomocą Javy 8, ale IMHO wygląda brzydko i trudno ją odczytać. Możemy utworzyć strumień wpisów map. Mamy już dwie implementacje Entry w java.util.AbstractMap, które sąSimpleEntry iSimpleImmutableEntry . W tym przykładzie możemy użyć former jako:

import java.util.AbstractMap.*;
private static final Map<Integer, String> myMap = Stream.of(
            new SimpleEntry<>(1, "one"),
            new SimpleEntry<>(2, "two"),
            new SimpleEntry<>(3, "three"),
            new SimpleEntry<>(4, "four"),
            new SimpleEntry<>(5, "five"),
            new SimpleEntry<>(6, "six"),
            new SimpleEntry<>(7, "seven"),
            new SimpleEntry<>(8, "eight"),
            new SimpleEntry<>(9, "nine"),
            new SimpleEntry<>(10, "ten"))
            .collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue));

W Javie 9 możemy również użyć Map.of, Jak zasugerował Tagir w jego odpowiedzi tutaj.

 16
Author: i_am_zero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:32

Może warto sprawdzić Kolekcje Google, np. filmy, które mają na swojej stronie. Zapewniają one różne sposoby inicjalizacji map i zestawów, a także zapewniają niezmienne Kolekcje.

Aktualizacja: ta Biblioteka ma teraz nazwę Guava .

 14
Author: Kaarel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 20:27:52

Lubię zajęcia anonimowe, bo łatwo sobie z tym poradzić:

public static final Map<?, ?> numbers = Collections.unmodifiableMap(new HashMap<Integer, String>() {
    {
        put(1, "some value");
                    //rest of code here
    }
});
 14
Author: Shushant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-28 06:12:40
public class Test {
    private static final Map<Integer, String> myMap;
    static {
        Map<Integer, String> aMap = ....;
        aMap.put(1, "one");
        aMap.put(2, "two");
        myMap = Collections.unmodifiableMap(aMap);
    }
}

Jeśli zadeklarujemy więcej niż jedną stałą, to kod będzie zapisany w statycznym bloku i będzie to trudne do utrzymania w przyszłości. Więc lepiej jest użyć anonimowej klasy.

public class Test {

    public static final Map numbers = Collections.unmodifiableMap(new HashMap(2, 1.0f){
        {
            put(1, "one");
            put(2, "two");
        }
    });
}

I sugeruje się użycie unmodifiableMap dla stałych innych mądrych, że nie może być traktowana jako stała.

 9
Author: Leninkumar Koppoju,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-03 08:30:03

Mógłbym zdecydowanie zasugerować styl "inicjalizacji podwójnej nawiasy" zamiast stylu statycznego bloku.

Ktoś może skomentować, że nie lubi anonimowych zajęć, napowietrznych, występów itp.

Ale bardziej rozważam czytelność i konserwację kodu. Z tego punktu widzenia stoję podwójny nawias jest lepszym stylem kodu, a nie metodą statyczną.

  1. elementy są zagnieżdżone i wbudowane.
  2. jest bardziej OO, nie proceduralne.
  3. wpływ wydajności jest naprawdę mały i można go zignorować.
  4. Lepsza obsługa konturów IDE (a nie wielu anonimowych statycznych bloków {})
  5. zachowałeś kilka linijek komentarza, aby doprowadzić ich do Związku.
  6. zapobiega ewentualnemu wyciekowi / wystąpieniu elementu z niezainicjalizowanego obiektu z wyjątku i optymalizatora kodu bajtowego.
  7. nie martw się o kolejność wykonania bloku statycznego.

Ponadto, jeśli znasz GC klasy anonymous, zawsze możesz przekonwertować go na normalną Hashmapę za pomocą new HashMap(Map map).

Możesz to zrobić, dopóki nie napotkasz innego problemu. Jeśli to zrobisz, powinieneś użyć complete innego stylu kodowania (np. no static, Factory class).
 7
Author: Dennis C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-12 04:29:03

Jak zwykle apache-commons ma odpowiednią metodę MapUtils.putAll(Mapa, obiekt[]):

Na przykład, aby utworzyć mapę kolorów:

Map<String, String> colorMap = MapUtils.putAll(new HashMap<String, String>(), new String[][] {
     {"RED", "#FF0000"},
     {"GREEN", "#00FF00"},
     {"BLUE", "#0000FF"}
 });
 7
Author: agad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-28 07:47:53

Oto moje ulubione, gdy nie chcę (lub nie mogę) używać guava ' s ImmutableMap.of(), lub jeśli potrzebuję mutable Map:

public static <A> Map<String, A> asMap(Object... keysAndValues) {
    return new LinkedHashMap<String, A>() {{
        for (int i = 0; i < keysAndValues.length - 1; i++) {
            put(keysAndValues[i].toString(), (A) keysAndValues[++i]);
        }
    }};
}

Jest bardzo zwarty i ignoruje wartości błądzące (tj. klucz końcowy bez wartości).

Użycie:

Map<String, String> one = asMap("1stKey", "1stVal", "2ndKey", "2ndVal");
Map<String, Object> two = asMap("1stKey", Boolean.TRUE, "2ndKey", new Integer(2));
 5
Author: neu242,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-22 12:34:28

Jeśli chcesz niezmodyfikowaną mapę, w końcu java 9 dodała fajną metodę fabryczną of do interfejsu Map. Podobna metoda jest również dodawana do Set, List.

Map<String, String> unmodifiableMap = Map.of("key1", "value1", "key2", "value2");

 5
Author: Bharanidharan K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-26 03:38:36

Anonimowa klasa, którą tworzysz, działa dobrze. Należy jednak pamiętać, że jest to klasa wewnętrzna i jako taka, będzie zawierać odniesienie do otaczającej instancji klasy. Więc przekonasz się, że nie możesz zrobić pewnych rzeczy z nim(używając XStream dla jednego). Dostaniesz kilka bardzo dziwnych błędów.

Powiedziawszy to, tak długo, jak jesteś świadomy, to takie podejście jest w porządku. Używam go najczęściej do inicjowania wszelkiego rodzaju kolekcji w zwięzły sposób.

EDIT: zaznaczono poprawnie w komentarzach, że jest to klasa statyczna. Najwyraźniej nie przeczytałem tego wystarczająco uważnie. Jednak Moje komentarze do nadal odnoszą się do anonimowych klas wewnętrznych.

 4
Author: Brian Agnew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-04 10:21:17

Jeśli chcesz czegoś zwięzłego i stosunkowo bezpiecznego, możesz po prostu zmienić sprawdzanie typu kompilacji na run-time:

static final Map<String, Integer> map = MapUtils.unmodifiableMap(
    String.class, Integer.class,
    "cat",  4,
    "dog",  2,
    "frog", 17
);

Ta implementacja powinna wychwycić wszelkie błędy:

import java.util.HashMap;

public abstract class MapUtils
{
    private MapUtils() { }

    public static <K, V> HashMap<K, V> unmodifiableMap(
            Class<? extends K> keyClazz,
            Class<? extends V> valClazz,
            Object...keyValues)
    {
        return Collections.<K, V>unmodifiableMap(makeMap(
            keyClazz,
            valClazz,
            keyValues));
    }

    public static <K, V> HashMap<K, V> makeMap(
            Class<? extends K> keyClazz,
            Class<? extends V> valClazz,
            Object...keyValues)
    {
        if (keyValues.length % 2 != 0)
        {
            throw new IllegalArgumentException(
                    "'keyValues' was formatted incorrectly!  "
                  + "(Expected an even length, but found '" + keyValues.length + "')");
        }

        HashMap<K, V> result = new HashMap<K, V>(keyValues.length / 2);

        for (int i = 0; i < keyValues.length;)
        {
            K key = cast(keyClazz, keyValues[i], i);
            ++i;
            V val = cast(valClazz, keyValues[i], i);
            ++i;
            result.put(key, val);
        }

        return result;
    }

    private static <T> T cast(Class<? extends T> clazz, Object object, int i)
    {
        try
        {
            return clazz.cast(object);
        }
        catch (ClassCastException e)
        {
            String objectName = (i % 2 == 0) ? "Key" : "Value";
            String format = "%s at index %d ('%s') wasn't assignable to type '%s'";
            throw new IllegalArgumentException(String.format(format, objectName, i, object.toString(), clazz.getSimpleName()), e);
        }
    }
}
 3
Author: Philip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-06 20:35:48

Wolę używać statycznego inicjalizatora, aby uniknąć generowania anonimowych klas( które nie mają dalszego celu), więc wymienię wskazówki inicjujące za pomocą statycznego inicjalizatora. Wszystkie wymienione rozwiązania / porady są bezpieczne dla typu.

Uwaga: pytanie nie mówi nic o uczynieniu mapy niezmodyfikowaną, więc pominę to, ale wiedz, że można to łatwo zrobić za pomocą Collections.unmodifiableMap(map).

Pierwsza wskazówka

Pierwsza wskazówka polega na tym, że możesz zrobić lokalne odniesienie do mapy i nadajesz mu skróconą nazwę:

private static final Map<Integer, String> myMap = new HashMap<>();
static {
    final Map<Integer, String> m = myMap; // Use short name!
    m.put(1, "one"); // Here referencing the local variable which is also faster!
    m.put(2, "two");
    m.put(3, "three");
}

Druga końcówka

Druga wskazówka polega na tym, że możesz utworzyć metodę pomocniczą do dodawania wpisów; możesz również upublicznić tę metodę pomocniczą, jeśli chcesz:

private static final Map<Integer, String> myMap2 = new HashMap<>();
static {
    p(1, "one"); // Calling the helper method.
    p(2, "two");
    p(3, "three");
}

private static void p(Integer k, String v) {
    myMap2.put(k, v);
}

Metoda pomocnicza nie jest jednak używana ponownie, ponieważ może dodawać tylko elementy do myMap2. Aby uczynić ją ponownie użyteczną, możemy uczynić samą mapę parametrem metody pomocniczej, ale wtedy kod inicjalizacji nie będzie krótszy.

Trzecia końcówka

The Trzecia wskazówka polega na tym, że możesz utworzyć klasę pomocniczą przypominającą budowniczego z funkcją wypełniania. Jest to naprawdę prosta, 10-liniowa Klasa pomocnicza, która jest bezpieczna dla typu:

public class Test {
    private static final Map<Integer, String> myMap3 = new HashMap<>();
    static {
        new B<>(myMap3)   // Instantiating the helper class with our map
            .p(1, "one")
            .p(2, "two")
            .p(3, "three");
    }
}

class B<K, V> {
    private final Map<K, V> m;

    public B(Map<K, V> m) {
        this.m = m;
    }

    public B<K, V> p(K k, V v) {
        m.put(k, v);
        return this; // Return this for chaining
    }
}
 3
Author: icza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-28 06:50:05

W Javie 8 zastosowałem następujący wzór:

private static final Map<String, Integer> MAP = Stream.of(
    new AbstractMap.SimpleImmutableEntry<>("key1", 1),
    new AbstractMap.SimpleImmutableEntry<>("key2", 2)
).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

To nie jest najbardziej zwięzłe i trochę rondo, ale

  • nie wymaga niczego poza java.util
  • jest bezpieczny i łatwo mieści różne typy klucza i wartości.
 3
Author: zrvan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-23 09:14:04

Możesz użyć StickyMap oraz MapEntry from Cactoos :

private static final Map<String, String> MAP = new StickyMap<>(
  new MapEntry<>("name", "Jeffrey"),
  new MapEntry<>("age", "35")
);
 3
Author: yegor256,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-10 09:09:10

Nie lubię statycznej składni inicjalizatora i nie jestem przekonany do anonimowych podklas. Generalnie zgadzam się ze wszystkimi minusami używania statycznych inicjalizatorów i wszystkimi minusami używania anonimowych podklas, o których wspomniano w odpowiedziach previusa. Z drugiej strony - plusy przedstawione w tych postach to dla mnie za mało. Preferuję statyczną metodę inicjalizacji:

public class MyClass {
    private static final Map<Integer, String> myMap = prepareMap();

    private static Map<Integer, String> prepareMap() {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "one");
        hashMap.put(2, "two");

        return hashMap;
    }
}
 2
Author: Stanisław Borowy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-28 07:00:27

Ponieważ Java nie obsługuje literałów map, instancje map muszą być zawsze jawnie tworzone i wypełniane.

Na szczęście możliwe jest przybliżenie zachowania liter map w Javie za pomocą Metody fabryczne.

na przykład:

public class LiteralMapFactory {

    // Creates a map from a list of entries
    @SafeVarargs
    public static <K, V> Map<K, V> mapOf(Map.Entry<K, V>... entries) {
        LinkedHashMap<K, V> map = new LinkedHashMap<>();
        for (Map.Entry<K, V> entry : entries) {
            map.put(entry.getKey(), entry.getValue());
        }
        return map;
    }
    // Creates a map entry
    public static <K, V> Map.Entry<K, V> entry(K key, V value) {
        return new AbstractMap.SimpleEntry<>(key, value);
    }

    public static void main(String[] args) {
        System.out.println(mapOf(entry("a", 1), entry("b", 2), entry("c", 3)));
    }
}

Wyjście:

{a= 1, b = 2, c = 3}

Jest to o wiele wygodniejsze niż tworzenie i wypełnianie mapy elementem naraz.

 2
Author: nazar_art,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-26 21:53:35

Twoje drugie podejście (inicjalizacja podwójnego nawiasu) jest uważane za anty wzorzec , więc wybrałbym pierwsze podejście.

Innym łatwym sposobem inicjalizacji statycznej mapy jest użycie tej funkcji użytkowej:

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

    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 = mapOf(1, "value1", 2, "value2");
Map<String, String> map2 = mapOf("key1", "value1", "key2", "value2");

Uwaga: W Java 9 można użyć Mapy.z

 2
Author: R. Oosterholt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-05 14:52:32

Nie widziałem podejścia, którego używam (i które polubiłem) w żadnych odpowiedziach, więc oto jest:

Nie lubię używać statycznych inicjalizatorów, ponieważ są niezgrabne, i nie lubię anonimowych klas, ponieważ tworzy nową klasę dla każdej instancji.

Zamiast tego wolę inicjalizację, która wygląda tak:

map(
    entry("keyA", "val1"),
    entry("keyB", "val2"),
    entry("keyC", "val3")
);

Niestety, te metody nie są częścią standardowej biblioteki Java, musisz więc utworzyć (lub użyć) bibliotekę narzędzi, która definiuje następujące metody:

 public static <K,V> Map<K,V> map(Map.Entry<K, ? extends V>... entries)
 public static <K,V> Map.Entry<K,V> entry(K key, V val)

(możesz użyć 'import static', aby uniknąć konieczności przedrostka nazwy metody)

Uznałem za przydatne dostarczenie podobnych metod statycznych dla innych kolekcji (list, set, sortedSet, sortedMap, itp.)

Nie jest tak przyjemna jak inicjalizacja obiektu json, ale jest to krok w tym kierunku, jeśli chodzi o czytelność.

 1
Author: josh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-03 20:46:29

JEP 269 zapewnia pewne fabryczne metody wygody dla API kolekcji. Te metody fabryczne nie są w obecnej wersji Java, która jest 8, ale są planowane dla Java 9 wydania.

Dla Map istnieją dwie metody fabryczne: of i ofEntries. Za pomocą of można przekazać przemienne pary klucz / wartość. Na przykład, aby utworzyć Map Jak {age: 27, major: cs}:

Map<String, Object> info = Map.of("age", 27, "major", "cs");

Obecnie istnieje dziesięć przeciążonych wersji dla of, więc możesz utworzyć mapę zawierającą dziesięć kluczy / wartości pary. Jeśli nie podoba Ci się to ograniczenie lub zmienny klucz / wartości, możesz użyć ofEntries:

Map<String, Object> info = Map.ofEntries(
                Map.entry("age", 27),
                Map.entry("major", "cs")
);

Zarówno of jak i ofEntries zwrócą niezmienne Map, więc nie można zmienić ich elementów Po zbudowaniu. Możesz wypróbować te funkcje za pomocą JDK 9 Early Access.

 1
Author: Ali Dehghani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-10 15:37:53

Przeczytałem odpowiedzi i postanowiłem napisać własny Kreator map. Zapraszamy do kopiowania i wklejania.

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * A tool for easy creation of a map. Code example:<br/>
 * {@code MapBuilder.of("name", "Forrest").and("surname", "Gump").build()}
 * @param <K> key type (inferred by constructor)
 * @param <V> value type (inferred by constructor)
 * @author Vlasec (for http://stackoverflow.com/a/30345279/1977151)
 */
public class MapBuilder <K, V> {
    private Map<K, V> map = new HashMap<>();

    /** Constructor that also enters the first entry. */
    private MapBuilder(K key, V value) {
        and(key, value);
    }

    /** Factory method that creates the builder and enters the first entry. */
    public static <A, B> MapBuilder<A, B> of(A key, B value) {
        return new MapBuilder<>(key, value);
    }

    /** Puts the key-value pair to the map and returns itself for method chaining */
    public MapBuilder<K, V> and(K key, V value) {
        map.put(key, value);
        return this;
    }

    /**
     * If no reference to builder is kept and both the key and value types are immutable,
     * the resulting map is immutable.
     * @return contents of MapBuilder as an unmodifiable map.
     */
    public Map<K, V> build() {
        return Collections.unmodifiableMap(map);
    }
}

EDIT: ostatnio dość często znajduję publiczną metodę statyczną of i trochę ją lubię. Dodałem go do kodu i uczyniłem konstruktora prywatnym, przechodząc w ten sposób na statyczny wzorzec metody fabrycznej.

 1
Author: Vlasec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-12 17:33:50

Jeśli musisz dodać tylko jedną wartość do mapy, możesz użyć Collections.singletonMap :

Map<K, V> map = Collections.singletonMap(key, value)
 1
Author: Stromata,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-30 21:28:08

Cóż... Lubię enum ;)

enum MyEnum {
    ONE   (1, "one"),
    TWO   (2, "two"),
    THREE (3, "three");

    int value;
    String name;

    MyEnum(int value, String name) {
        this.value = value;
        this.name = name;
    }

    static final Map<Integer, String> MAP = Stream.of( values() )
            .collect( Collectors.toMap( e -> e.value, e -> e.name ) );
}
 1
Author: jglatre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-25 16:28:13