1574

Is there some way of initializing a Java HashMap like this?:

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

What would be the correct syntax? I have not found anything regarding this. Is this possible? I am looking for the shortest/fastest way to put some "final/static" values in a map that never change and are known in advance when creating the Map.

Freedom_Ben
  • 11,247
  • 10
  • 69
  • 89
jens
  • 16,455
  • 4
  • 21
  • 20
  • 1
    relatd: http://stackoverflow.com/questions/2041778/initialize-java-hashset-values-by-construction/2041789#2041789 – Bozho Jul 23 '11 at 18:55
  • Closely related: http://stackoverflow.com/questions/507602/how-to-initialise-a-static-map-in-java (Both questions are about initialising a constant map with static, final values.) – Jonik Jul 18 '13 at 11:27
  • http://stackoverflow.com/questions/36951414/initialize-a-map-hashmap-in-java/36951468#36951468 – Ramkumar Pillai Apr 30 '16 at 06:22
  • In Java 9: http://www.techiedelight.com/initialize-map-java9/ – Kamil Tomasz Jarmusik Feb 04 '18 at 15:32
  • If you use apache.commons.collections, you can use https://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/MapUtils.html#putAll(java.util.Map,%20java.lang.Object[]) – ax. Mar 21 '18 at 17:55
  • Since no answer is allowed here any more, see https://stackoverflow.com/questions/507602/how-can-i-initialise-a-static-map/52266947#52266947 – Gerold Broser Sep 11 '18 at 00:44
  • Check [soyuz-to](https://github.com/thedocs-io/soyuz-to) - `to.map("myKey", "myValue")`. It very simple and has a lot of other useful features – fedor.belov Aug 17 '19 at 20:50
  • 4
    **Not** a duplicate of [the linked Question](https://stackoverflow.com/q/507602/642706). That Question is about `static` while this Question is asking about instantiating by literal syntax. **Voting to re-open.** Perhaps this Question is a duplicate of some other Question; if so, re-open and close again by linking to a Question that is truly an original of this. – Basil Bourque Dec 17 '19 at 02:13

22 Answers22

2076

All Versions

In case you happen to need just a single entry: There is Collections.singletonMap("key", "value").

For Java Version 9 or higher:

Yes, this is possible now. In Java 9 a couple of factory methods have been added that simplify the creation of maps :

// 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")
);

In the example above both test and test2 will be the same, just with different ways of expressing the Map. The Map.of method is defined for up to ten elements in the map, while the Map.ofEntries method will have no such limit.

Note that in this case the resulting map will be an immutable map. If you want the map to be mutable, you could copy it again, e.g. using mutableMap = new HashMap<>(Map.of("a", "b"));. Also note that in this case keys and values must not be null.

(See also JEP 269 and the Javadoc)

For up to Java Version 8:

No, you will have to add all the elements manually. You can use an initializer in an anonymous subclass to make the syntax a little bit shorter:

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

However, the anonymous subclass might introduce unwanted behavior in some cases. This includes for example:

  • It generates an additional class which increases memory consumption, disk space consumption and startup-time
  • In case of a non-static method: It holds a reference to the object the creating method was called upon. That means the object of the outer class cannot be garbage collected while the created map object is still referenced, thus blocking additional memory

Using a function for initialization will also enable you to generate a map in an initializer, but avoids nasty side-effects:

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;
}
yankee
  • 38,872
  • 15
  • 103
  • 162
  • 3
    This won't work if you want to initial the elements in a function... – Michael Aug 15 '15 at 23:49
  • 12
    @Michael: Well yes, if you want to use a function than you cannot use a not-function. But why do you want to? – yankee Aug 16 '15 at 08:05
  • 9
    and for the cases when you need a Map with a single entry there's `Collections.singletonMap()` :) – skwisgaar Aug 16 '17 at 17:47
  • 3
    Now that stable Java 9 has been released, I prefer [this link for Javadoc](https://docs.oracle.com/javase/9/docs/api/java/util/Map.html). And +1 because one less dependency! – Franklin Yu Oct 03 '17 at 14:14
  • 3
    Where is Java 9 `entry` documented? – Brent Bradburn Jul 27 '18 at 16:42
  • 1
    @nobar: In the very last link at the end of my post. – yankee Jul 28 '18 at 17:27
  • "this works for up to 10 elements", what if we want 11 elements? –  Jan 29 '19 at 07:47
  • @MrCholo: In this case use one of the other possibilities. – yankee Jan 29 '19 at 19:57
  • 3
    Should be `Map.entry`, not `entry`, but works otherwise. Thanks! – Cameron Hudson Feb 07 '19 at 16:25
  • 2
    @CameronHudson: If you use a `static import` then it is just `entry`. – yankee Feb 08 '19 at 17:09
  • @yankee Oh thanks, TIL. Here is some more info for those like me who use the Eclipse default of non-static imports: https://www.geeksforgeeks.org/static-import-java/ – Cameron Hudson Feb 09 '19 at 16:11
  • @yankee can you elaborate on "However, the anonymous subclass might introduce unwanted behaviour in some cases."? – Thrasi Apr 10 '19 at 09:49
  • @Thrasi: I added two examples. – yankee Jul 31 '19 at 18:40
  • Nice answer. Keep in mind that, as the doc states, Map.entry accepts neither null key nor null value, so it's not recommended for cases where values might be null. – Diego dos Santos Dec 04 '19 at 17:23
  • The lightweight syntax for Java 9 is nice, but does not work when a key is null. – akim Jul 30 '21 at 10:13
  • @yankee This question asks how to directly initialize a HashMap. `Collections.singletonMap()` doesn't work for this because `HashMap` doesn't implement a `Collection`. This can cause type errors in your code, and since `Map` can't be typecast to `HashMap`, or vice versa, this just won't work. – tbatch Feb 23 '22 at 15:06
  • 1
    @skidwiz The original question should probably be reworded - I don't think the question asker is particularly interested in the actual implementation of map, as long as it's a map, i.e. is an instance of a concrete class that implements the `Map` interface. Whatever `Collections.singletonMap()` creates, it implements the `Map` interface, because that's what its signature says. Not sure what you mean by "`HashMap` doesn't implement a `Collection`" - `Map` does not inherit from `Collection` either, so I don't see how this is relevant. – Frans Mar 28 '22 at 12:29
  • note - key vals must not be null – Gaurav Sep 14 '22 at 20:50
1156

This is one way.

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

However, you should be careful and make sure that you understand the above code (it creates a new class that inherits from HashMap). Therefore, you should read more here: http://www.c2.com/cgi/wiki?DoubleBraceInitialization , or simply use Guava:

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

ImmutableMap.of works for up to 5 entries. Otherwise, use the builder: source.

Druckles
  • 3,161
  • 2
  • 41
  • 65
gregory561
  • 14,866
  • 2
  • 23
  • 25
  • 89
    It works but it's ugly and has invisible side effects that the user should understand before doing it - for example, generating an entire anonymous class on the spot. – jprete Jul 23 '11 at 18:48
  • 109
    yep, that is way I wrote about being careful and gave a link to the description. – gregory561 Jul 23 '11 at 18:50
  • 6
    Great link. The reference in that link to [GreencoddsTenthRuleOfProgramming](http://www.c2.com/cgi/wiki?GreencoddsTenthRuleOfProgramming) is worth the read. – michaelok May 16 '13 at 21:10
  • This is a feasible option for initializing a Map in an interface (where you cannot use a static block). – Mark Aug 30 '14 at 08:32
  • 21
    can you add "as ImmutableMap.builder.put("k1","v1").put("k2","v2").build()" as the "of" method is limited to 5 pairs at maximum ? – kommradHomer Oct 15 '14 at 09:15
  • 3
    + for Guava http://google.github.io/guava/releases/18.0/api/docs/com/google/common/collect/ImmutableMap.html – Dan Jay Jun 18 '15 at 11:04
  • 2
    Year 2016. I keep Googling the same question and coming to the same answer. Wish I could upvote each time.. – saiyancoder Jul 17 '16 at 18:06
  • I use this method to send data to the Firebase database. If you don't create a new Hashmap for each 'setValue' you can get concurrent access exceptions. – Androidcoder Nov 06 '16 at 18:25
  • btw using `ImmutableMap.of` gives me an `unchecked assignment` warning. – Yar Aug 08 '17 at 01:29
  • This cant be used when you have a variable inside. You have make it final – madhairsilence Feb 06 '18 at 12:45
  • But guava's immutableMap only support 5 key-value pairs most. – sudoz Sep 02 '19 at 04:08
  • Double curly initialization is creating an anonymous class, thus contains a reference to the outer class and will sometimes cause the outer class to exist even after it should be garbage collected. So it will cause a memory leak. – Yossarian42 Feb 12 '20 at 17:50
  • Another warning: A HashMap create this way may result in the string `"null"` when trying to serialize it to JSON via `new Gson().toJson(h)`. (Side node: `getClass()` on a normal HashMap object will return `"HashMap"`. But on an object created like this it will be something like `"Main$1"` (an anonymous class as mentioned by others)). – jox Feb 23 '22 at 11:22
368

If you allow 3rd party libs, you can use Guava's ImmutableMap to achieve literal-like brevity:

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

This works for up to 5 key/value pairs, otherwise you can use its builder:

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


  • note that Guava's ImmutableMap implementation differs from Java's HashMap implementation (most notably it is immutable and does not permit null keys/values)
  • for more info, see Guava's user guide article on its immutable collection types
Jens Hoffmann
  • 6,699
  • 2
  • 25
  • 31
  • 29
    Also, guava has ImmutableMap.builder.put("k1","v1").put("k2","v2").build(); – Xetius Oct 09 '13 at 13:50
  • 21
    ImmutableMap is not the same as a HashMap, as it will fail on null values, whereas map HashMap will not. – Gewthen Mar 06 '14 at 19:04
  • 3
    Just to help others that might face this issue. You have to type the builder to make it a Map, like this: Map test = ImmutableMap.builder().put("k1", "v1").put("k2", "v2").build(); – Thiago Mar 09 '15 at 20:35
121

There is no direct way to do this - As of 2021, Java has no Map literals (yet - I think they were proposed for Java 8, but didn't make it).

Some people like this:

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

This creates an anonymous subclass of HashMap, whose instance initializer puts these values. (By the way, a map can't contain twice the same value, your second put will overwrite the first one. I'll use different values for the next examples.)

The normal way would be this (for a local variable):

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

If your test map is an instance variable, put the initialization in a constructor or instance initializer:

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

If your test map is a class variable, put the initialization in a static initializer:

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

If you want your map to never change, you should after the initialization wrap your map by Collections.unmodifiableMap(...). You can do this in a static initializer too:

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

(I'm not sure if you can now make test final ... try it out and report here.)

Since Java 9, you also have the Map.of(...) and Map.ofEntries() syntax, as explained in the answer from yankee.

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
65
Map<String,String> test = new HashMap<String, String>()
{
    {
        put(key1, value1);
        put(key2, value2);
    }
};
Shaggy Frog
  • 27,575
  • 16
  • 91
  • 128
  • Simple and to the point. I think this with an extended commentary section would be the best answer. – ooolala Jan 30 '16 at 05:05
  • Why doesn't this have more votes? Is it not better than the other answers? I looks a lot cleaner. Could someone explain to me, please? Because I might end up using this one. Thanks. – hello_its_me Apr 10 '16 at 14:26
  • 17
    There are memory implications that should be noted though. https://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/ – Alkanshel Jun 09 '16 at 18:05
  • 1
    @Amalgovinus Basically, by creating a new subclass, you are hard-coding the type arguments from `HashMap` into this subclass. This can only work if you actually provide them. (With a new (empty) HashMap, the type arguments are not relevant.) – Paŭlo Ebermann Jul 12 '16 at 08:22
  • 2
    I like the cleanliness of it, but it creates unnecessary anonymous class and has the problems described here: http://www.c2.com/cgi/wiki?DoubleBraceInitialization – udachny Aug 25 '16 at 08:01
  • 1
    @hello_its_me: Because Its same as http://stackoverflow.com/a/6802512/1386911 answer, just the formatting different. And in this case this extended formatting has no additional value on top of compact format for readability. – Daniel Hári Oct 31 '16 at 21:51
  • Can anyone explain the synax here? The nested `{{}}` . – ZhaoGang Sep 29 '19 at 07:31
46

An alternative, using plain Java 7 classes and varargs: create a class HashMapBuilder with this method:

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;
}

Use the method like this:

HashMap<String,String> data = HashMapBuilder.build("key1","value1","key2","value2");
Aerthel
  • 659
  • 8
  • 8
  • I wrote an answer inspired by yours: https://stackoverflow.com/questions/507602/how-can-i-initialise-a-static-map/52266947#52266947 – Gerold Broser Sep 11 '18 at 01:38
  • 2
    Another solution with Apache Utils that is never mentioned but is readable, using prior Java versions: MapUtils.putAll(new HashMap(), new Object[] { "My key", "my value", ... – Rolintocour Oct 25 '18 at 06:41
  • An elegant, and easy-to-understand example! And the Apache Utils is also great. – Tihamer Jan 29 '21 at 18:01
16

tl;dr

Use Map.of… methods in Java 9 and later.

Map< String , String > animalSounds =
    Map.of(
        "dog"  , "bark" ,   // key , value
        "cat"  , "meow" ,   // key , value
        "bird" , "chirp"    // key , value
    )
;

Map.of

Java 9 added a series of Map.of static methods to do just what you want: Instantiate an immutable Map using literal syntax.

The map (a collection of entries) is immutable, so you cannot add or remove entries after instantiating. Also, the key and the value of each entry is immutable, cannot be changed. See the Javadoc for other rules, such as no NULLs allowed, no duplicate keys allowed, and the iteration order of mappings is arbitrary.

Let's look at these methods, using some sample data for a map of day-of-week to a person who we expect will work on that day.

Person alice = new Person( "Alice" );
Person bob = new Person( "Bob" );
Person carol = new Person( "Carol" );

Map.of()

Map.of creates an empty Map. Unmodifiable, so you cannot add entries. Here is an example of such a map, empty with no entries.

Map < DayOfWeek, Person > dailyWorkerEmpty = Map.of();

dailyWorkerEmpty.toString(): {}

Map.of( … )

Map.of( k , v , k , v , …) are several methods that take 1 to 10 key-value pairs. Here is an example of two entries.

Map < DayOfWeek, Person > weekendWorker = 
        Map.of( 
            DayOfWeek.SATURDAY , alice ,     // key , value
            DayOfWeek.SUNDAY , bob           // key , value
        )
;

weekendWorker.toString(): {SUNDAY=Person{ name='Bob' }, SATURDAY=Person{ name='Alice' }}

Map.ofEntries( … )

Map.ofEntries( Map.Entry , … ) takes any number of objects implementing the Map.Entry interface. Java bundles two classes implementing that interface, one mutable, the other immutable: AbstractMap.SimpleEntry, AbstractMap.SimpleImmutableEntry. But we need not specify a concrete class. We merely need to call Map.entry( k , v ) method, pass our key and our value, and we get back an object of a some class implementing Map.Entry interface.

Map < DayOfWeek, Person > weekdayWorker = Map.ofEntries(
        Map.entry( DayOfWeek.MONDAY , alice ) ,            // Call to `Map.entry` method returns an object implementing `Map.Entry`. 
        Map.entry( DayOfWeek.TUESDAY , bob ) ,
        Map.entry( DayOfWeek.WEDNESDAY , bob ) ,
        Map.entry( DayOfWeek.THURSDAY , carol ) ,
        Map.entry( DayOfWeek.FRIDAY , carol )
);

weekdayWorker.toString(): {WEDNESDAY=Person{ name='Bob' }, TUESDAY=Person{ name='Bob' }, THURSDAY=Person{ name='Carol' }, FRIDAY=Person{ name='Carol' }, MONDAY=Person{ name='Alice' }}

Map.copyOf

Java 10 added the method Map.copyOf. Pass an existing map, get back an immutable copy of that map.

For efficiency, if the passed map is already truly immutable, the copyOf method returns a reference to the original without manufacturing a new map.

About Collections.unmodifiableMap

Tip: Prefer Map.copyOf over Collections.unmodifiableMap if you need/expect a truly immutable map.

The Collections method produces a view onto the original map, a mere wrapper, not a true copy. The upside: Being a mere view has the benefit of conserving memory. The downside: Modifications to the original show through.

If the original map gets modified (put, remove, etc.), the supposedly-unmodifiable will actually show the modification. In contrast, the Map.copyOf does indeed produce a true copy of the passed map if not already truly immutable.

record Person( String name ) { }
Person alice = new Person ( "Alice" );
Person bob = new Person ( "Bob" );
Map < DayOfWeek, Person > weekendWorkerMutable = HashMap.newHashMap ( 2 );
weekendWorkerMutable.put ( DayOfWeek.SATURDAY , bob );
weekendWorkerMutable.put ( DayOfWeek.SUNDAY , bob );
System.out.println ( "weekendWorkerMutable = " + weekendWorkerMutable );

Map < DayOfWeek, Person > weekendWorkerSupposedlyUnmodifiable = Collections.unmodifiableMap ( weekendWorkerMutable );
System.out.println ( "weekendWorkerSupposedlyUnmodifiable = " + weekendWorkerSupposedlyUnmodifiable );
Map < DayOfWeek, Person > trueCopy = Map.copyOf ( weekendWorkerSupposedlyUnmodifiable );
System.out.println ( "trueCopy = " + trueCopy );

weekendWorkerMutable.put ( DayOfWeek.SATURDAY , alice );  // <--- Modify the original.

System.out.println ( " ----- After mutating the original mutable map  ----- " );
System.out.println ( "weekendWorkerSupposedlyUnmodifiable = " + weekendWorkerSupposedlyUnmodifiable );
System.out.println ( "trueCopy = " + trueCopy );

When run:

  • We see that the supposedly unmodifiable is indeed modifiable indirectly, by modifying the original map on which the unmodifiable map is a view.
  • In contrast, the copyOf method produces a true copy, showing Bob as working the entire weekend even after assigning Alice.
weekendWorkerMutable = {SATURDAY=Person[name=Bob], SUNDAY=Person[name=Bob]}
weekendWorkerSupposedlyUnmodifiable = {SATURDAY=Person[name=Bob], SUNDAY=Person[name=Bob]}
trueCopy = {SUNDAY=Person[name=Bob], SATURDAY=Person[name=Bob]}
 ----- After mutating the original mutable map  ----- 
weekendWorkerSupposedlyUnmodifiable = {SATURDAY=Person[name=Alice], SUNDAY=Person[name=Bob]}
trueCopy = {SUNDAY=Person[name=Bob], SATURDAY=Person[name=Bob]}

Notes

Notice that the iterator order of maps produced via Map.of are not guaranteed. The entries have an arbitrary order. Do not write code based on the order seen, as the documentation warns the order is subject to change.

Note that all of these Map.of… methods return a Map of an unspecified class. The underlying concrete class may even vary from one version of Java to another. This anonymity enables Java to choose from various implementations, whatever optimally fits your particular data. For example, if your keys come from an enum, Java might use an EnumMap under the covers.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
15

JAVA 8

In plain java 8 you also have the possibility of using Streams/Collectors to do the job.

Map<String, String> myMap = Stream.of(
         new SimpleEntry<>("key1", "value1"),
         new SimpleEntry<>("key2", "value2"),
         new SimpleEntry<>("key3", "value3"))
        .collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));

This has the advantage of not creating an Anonymous class.

Note that the imports are:

import static java.util.stream.Collectors.toMap;
import java.util.AbstractMap.SimpleEntry;

Of course, as noted in other answers, in java 9 onwards you have simpler ways of doing the same.

Johnny Willer
  • 3,717
  • 3
  • 27
  • 51
  • 1
    In case you are using apache commons, you could also use `Pair.of()` instead of `new SimpleEntry<>` and then `Pair::getKey` and `Pair::getValue` – Tobias Grunwald Jun 21 '21 at 10:54
6

I would like to give a brief warning to Johnny Willer's answer.

Collectors.toMap relies on Map.merge and does not expect null values, so it will throw a NullPointerException as it was described in this bug report: https://bugs.openjdk.java.net/browse/JDK-8148463

Also, if a key appears several times, the default Collectors.toMap will throw an IllegalStateException.

An alternative way to get a map with null values using a builder syntax on Java 8 is writing a custom collector backed by a HashMap (because it does allow null values):

Map<String, String> myMap = Stream.of(
         new SimpleEntry<>("key1", "value1"),
         new SimpleEntry<>("key2", (String) null),
         new SimpleEntry<>("key3", "value3"),
         new SimpleEntry<>("key1", "value1updated"))
        .collect(HashMap::new,
                (map, entry) -> map.put(entry.getKey(),
                                        entry.getValue()),
                HashMap::putAll);
BeardOverflow
  • 938
  • 12
  • 15
  • 1
    simpler to use `entry(...)` over `new SimpleEntry<>(...)` (import `java.util.Map.entry`) – Mugen Apr 26 '22 at 08:46
3

We use a simple utility class to initialize Maps in a fluent way:

Map<String, String> map = MapInit
    .init("key1", "value1")
    .put("key2", "value2")
    .put("key3", "value3")
    .getMap();

The utility class isn't limited neither regarding the type of keys and values nor regarding the amount of entries nor regarding the type of the resulting Map.

The utility class looks like the following:

public class MapInit<K, V, T extends Map<K, V>> {
    private final T map;


    private MapInit(final T map) {
        this.map = map;
    }

    public T getMap() {
        return this.map;
    }

    public static <K, V> MapInit<K, V, HashMap<K, V>> init(final K key, final V value) {
        return init(HashMap::new, key, value);
    }

    public static <K, V, T extends Map<K, V>> MapInit<K, V, T> init(final Supplier<T> mapSupplier, final K key, final V value) {
        return new MapInit<>(mapSupplier.get()) //
                .put(key, value);
    }

    public MapInit<K, V, T> put(final K key, final V value) {
        this.map.put(key, value);
        return this;
    }
}
  • Did you invent this yourself? Please don't. Shorter and better solutions already exist, i.e. at https://www.baeldung.com/java-initialize-hashmap and on this page. – MarkHu Dec 01 '22 at 02:02
3

I found a great article by baeldung that lists several ways to do this in different Java versions.

A couple of interesting ways that can be handy are

For any Java version

public static Map<String, String> articleMapOne;
static {
    articleMapOne = new HashMap<>();
    articleMapOne.put("ar01", "Intro to Map");
    articleMapOne.put("ar02", "Some article");
}

For Java 8 using streams

Map<String, String> map = Stream.of(new String[][] {
  { "Hello", "World" }, 
  { "John", "Doe" }, 
}).collect(Collectors.toMap(data -> data[0], data -> data[1]));
avp
  • 2,892
  • 28
  • 34
2

We can use AbstractMap Class having SimpleEntry which allows the creation of immutable map

Map<String, String> map5 = Stream.of(
    new AbstractMap.SimpleEntry<>("Sakshi","java"),
    new AbstractMap.SimpleEntry<>("fine","python")
    ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    
    System.out.println(map5.get("Sakshi"));
    map5.put("Shiva", "Javascript");
    System.out.println(map5.get("Shiva"));// here we can add multiple entries.
Ruli
  • 2,592
  • 12
  • 30
  • 40
1

You could possibly make your own Map.of (which is only available in Java 9 and higher) method easily in 2 easy ways

Make it with a set amount of parameters

Example

public <K,V> Map<K,V> mapOf(K k1, V v1, K k2, V v2 /* perhaps more parameters */) {
    return new HashMap<K, V>() {{
      put(k1, v1);
      put(k2,  v2);
      // etc...
    }};
}

Make it using a List

You can also make this using a list, instead of making a lot of methods for a certain set of parameters.

Example

public <K, V> Map<K, V> mapOf(List<K> keys, List<V> values) {
   if(keys.size() != values.size()) {
        throw new IndexOutOfBoundsException("amount of keys and values is not equal");
    }

    return new HashMap<K, V>() {{
        IntStream.range(0, keys.size()).forEach(index -> put(keys.get(index), values.get(index)));
    }};
}

Note It is not recommended to use this for everything as this makes an anonymous class every time you use this.

NotNV6
  • 11
  • 3
1

If you need to place only one key-value pair, you can use Collections.singletonMap(key, value);

1

With Java 8 or less

You can use static block to initialize a map with some values. Example :

public static Map<String,String> test = new HashMap<String, String>

static {
    test.put("test","test");
    test.put("test1","test");
}

With Java 9 or more

You can use Map.of() method to initialize a map with some values while declaring. Example :

public static Map<String,String> test = Map.of("test","test","test1","test");
Furkan Yavuz
  • 1,858
  • 5
  • 30
  • 51
1

Following code can do the trick in Java 8:

Map<String, Integer> map = Stream.of(new Object[][] { 
     { "data1", 1 }, 
     { "data2", 2 }, 
 }).collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));

credits:

nurb
  • 325
  • 3
  • 6
1

Simple way to do this:

public static Map<String, String> mapWithValues(String...values) {
    Map<String, String> map = new HashMap<String, String>();
    
    for (int x = 0; x < values.length; x = x+2) {
        map.put(values[x], values[x+1]);
    }
    
    return map;
}
Milton Bertachini
  • 316
  • 1
  • 2
  • 8
  • Isn't this just a variant on the non-desirable old pre-Java9 method described in the most popular answer? – MarkHu Jul 02 '21 at 16:53
1

If it's an instance variable, then an instance initialization block is definitely the way to go, especially if you can't use Map.of() because you need a different type of map.

But if you're feeling frisky, you could use a Java 8 Supplier (not recommended).

private final Map<String,Runnable> games = ((Supplier<Map<String,Runnable>>)() -> {
  Map<String,Runnable> map = new LinkedHashMap<>();

  map.put("solarus",this::playSolarus);
  map.put("lichess",this::playLichess);

  return map;
}).get();

Or make your own functional interface (looks fine to me):

@FunctionalInterface
public interface MapMaker<M> {
  static <M extends Map<K,V>,K,V> M make(M map,MapMaker<M> maker) {
    maker.build(map);
    return map;
  }

  void build(M map);
}

// Can use LinkedHashMap!
private final Map<String,Runnable> games = MapMaker.make(
    new LinkedHashMap<>(),(map) -> {
      map.put("solarus",this::playSolarus);
      map.put("lichess",this::playLichess);
    });
esotericpig
  • 282
  • 1
  • 3
  • 14
0

Unfortunately, using varargs if the type of the keys and values are not the same is not very reasonable as you'd have to use Object... and lose type safety completely. If you always want to create e.g. a Map<String, String>, of course a toMap(String... args) would be possible though, but not very pretty as it would be easy to mix up keys and values, and an odd number of arguments would be invalid.

You could create a sub-class of HashMap that has a chainable method like

public class ChainableMap<K, V> extends HashMap<K, V> {
  public ChainableMap<K, V> set(K k, V v) {
    put(k, v);
    return this;
  }
}

and use it like new ChainableMap<String, Object>().set("a", 1).set("b", "foo")

Another approach is to use the common builder pattern:

public class MapBuilder<K, V> {
  private Map<K, V> mMap = new HashMap<>();

  public MapBuilder<K, V> put(K k, V v) {
    mMap.put(k, v);
    return this;
  }

  public Map<K, V> build() {
    return mMap;
  }
}

and use it like new MapBuilder<String, Object>().put("a", 1).put("b", "foo").build();

However, the solution I've used now and then utilizes varargs and the Pair class:

public class Maps {
  public static <K, V> Map<K, V> of(Pair<K, V>... pairs) {
    Map<K, V> = new HashMap<>();

    for (Pair<K, V> pair : pairs) {
      map.put(pair.first, pair.second);
    }

    return map;
  }
}

Map<String, Object> map = Maps.of(Pair.create("a", 1), Pair.create("b", "foo");

The verbosity of Pair.create() bothers me a bit, but this works quite fine. If you don't mind static imports you could of course create a helper:

public <K, V> Pair<K, V> p(K k, V v) {
  return Pair.create(k, v);
}

Map<String, Object> map = Maps.of(p("a", 1), p("b", "foo");

(Instead of Pair one could imagine using Map.Entry, but since it's an interface it requires an implementing class and/or a helper factory method. It's also not immutable, and contains other logic not useful for this task.)

JHH
  • 8,567
  • 8
  • 47
  • 91
0

You can use Streams In Java 8 (this is exmaple of Set):

@Test
public void whenInitializeUnmodifiableSetWithDoubleBrace_containsElements() {
    Set<String> countries = Stream.of("India", "USSR", "USA")
      .collect(collectingAndThen(toSet(), Collections::unmodifiableSet));

    assertTrue(countries.contains("India"));
}

Ref: https://www.baeldung.com/java-double-brace-initialization

Robocide
  • 6,353
  • 4
  • 37
  • 41
0

You can create a method to initialize the map like in this example below:

Map<String, Integer> initializeMap()
{
  Map<String, Integer> ret = new HashMap<>();

  //populate ret
  ...

  return ret;
}

//call
Map<String, Integer> map = initializeMap();
PaulNUK
  • 4,774
  • 2
  • 30
  • 58
Alan
  • 99
  • 4
  • 10
0

Map.of() seems most universal and least limited. Here, it takes care of non object input values automaticaly :

List<Map<String, Object> certs = new ArrayList<>(){{ add( Map.of(
    "TAG",          Obj1 // Object
    "TAGGED_ID",    1L //Long
    "DEGREE",       "PARENT" // String
    "DATE",         LocalDate.now() // LocalDate
));}};

Note that maps created by static Map.of(..) constuctor don't allow neither keys nor values to be null .

user16547619
  • 199
  • 1
  • 4