6

Is there a way to create a map with keys and values at the same time (I mean a one-line code)? For example, I create a map named map, and I need to use the method "put" whenever I want to add a new pair of key/value. Is there a shorter way to populate a map when we create it?

Map<String, String> map = new HashMap<String, String>();
    map.put("A", "32");
    map.put("C", "34");
    map.put("T", "53");
tmeach
  • 91
  • 1
  • 1
  • 2
  • 2
    What's the value of doing something in one line ? Readability ? No. Maintainability ? No. Performance ? No. – Nir Alfasi Feb 07 '17 at 22:37
  • 2
    Just for fun, no? – Andremoniy Feb 07 '17 at 22:38
  • @Andremoniy I can think about many other things that will be more fun, but that's primarily opinion based ;) – Nir Alfasi Feb 07 '17 at 22:39
  • What's stopping you from putting it all on one line? – shmosel Feb 07 '17 at 22:40
  • 1
    @alfasin One value would be if you needed to pass as a parameter, or return a map from a lambda. E.g., `configure(Map.of("width", 640, "height", 480))` Any place you would want to write it as an expression, in other words. – David Conrad Feb 07 '17 at 23:08
  • @DavidConrad that's exactly the purpose of `of()` method - to *not* do everything in one line but rather have another method that does it for you, while keeping the code concise without compromising its readability! – Nir Alfasi Feb 07 '17 at 23:36

2 Answers2

14

Convenience Factory Methods for Collections

In Java 9 there are some new Map helper methods defined by JEP 269: Convenience Factory Methods for Collections.

Map<String, String> map = Map.of("A", "32", "C", "34", "T", "53");

But this only works for up to 10 entries. For more than ten, use:

import static java.util.Map.entry;

Map<String, String> map = Map.ofEntries(
    entry("A", "32"), entry("C", "34"), entry("T", "53"));

You could write similar helper methods if you needed to do it in earlier versions.

Community
  • 1
  • 1
David Conrad
  • 15,432
  • 2
  • 42
  • 54
10

In Java 8 you can use the following methods which are explained here:

If you just need a quick immutable single-entry or empty map

Map<String, String> map = Collections.singletonMap("A", "32");
Map<String, String> map = Collections.emptyMap();

Using Streams

Suppose you have your data in an ArrayList of objects that contain your Data that can be accessed with arbitrary getters, you can use the Streams API:

List<Data> dataList = new ArrayList<>();
// .... populate data list
Map<String, Integer> nameToAge = dataList.stream().collect(
    Collectors.toMap(Data::getFooAsKey, Data::getBarAsValue)
);

...or using an inline map approach (if you don't have/need/want to create dataList):

Map<String, Integer> map = Stream.of( 
    new Data("A", "32"), new Data("C", "34"), new Data("C", "34")
).collect(Collectors.toMap(User::getFooAsKey, User::getBarAsValue));

Anonymous Subclass (discouraged)

Map<String, String> map = new HashMap<String, String>({{
    put("A", "32");
    put("C", "34");
    put("T", "53");
}});

As this method can cause memory leaks it is strongly discouraged.

Using Guava

Map<String, String> immutableMap = Maps.newHashMap(
    ImmutableMap.of("A", "32", "C", "34", "T", "53")
);

Starting with Java 9 there's superior syntactic sugar available, as outlined in David's answer.

Philzen
  • 3,945
  • 30
  • 46
  • Cool! Could you provide, more details about memory leaks in Anonymous Subclass implementation. please? – stanley Dec 24 '21 at 08:06
  • 1
    @stanley Basically all non-static inner classes bear the potential to cause memory leaks b/c of the way the GC works, as explained in [this SO post](https://stackoverflow.com/questions/10864853/). Regarding the anonymous subclass initialization trick, asking ecosia / google returns a number of writeups on this, for example [this one](https://web.archive.org/web/20210226184817/https://jesperdj.com/2016/07/19/dont-use-the-double-brace-initialization-trick/) (i have linked that in the answer now). – Philzen Dec 26 '21 at 20:41