-1

I want to instantiate a Java hashmap with literals in Java. I am using Java 8.

I have seen from Functional Programming in Java book that you can do this with Lists:

final List<String> cities = Arrays.asList("Albany", "Boulder", "Chicago", "Denver", "Eugene");

But I haven't seen how you can do a similar thing with hash maps.

I can create the hash map like this:

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

public class ShortestPath1 {
    public static void main(final String[] args) {
        final Map<String,Integer> station2nlc = new HashMap<String, Integer>(); 
        station2nlc.put("Ealing Broadway", 319000); 
        station2nlc.put("Ealing Common", 319005); 
        station2nlc.put("Acton Town LT", 50000); 
        station2nlc.put( "Chiswick Park LT", 54500); 
        station2nlc.put( "Turnham Green LT", 73400);
        station2nlc.put( "Stamford Brook LT", 71300); 
        station2nlc.put( "Ravenscourt Park LT", 68200); 
        station2nlc.put( "Hammersmith LT", 59300);
        station2nlc.put( "Barons Court LT", 51600); 
        station2nlc.put( "West Kensington", 76000); 
        station2nlc.put( "Earls Court LT", 56200); 
        station2nlc.put( "West Kensington LT", 76000); 

        System.out.println("Ealing has NLC: " + station2nlc.get("Ealing Broadway"));
    }
}

But this syntax implies that Java is building the hashmap per line instruction. Which it probably is.

For comparison, the example below in C++ is what I was thinking would be possible:

#include <string>
#include <unordered_map>
#include <iostream>

int main() {
    std::unordered_map<std::string, int> station2nlc(
    {
        { "Ealing Broadway", 319000 },
        { "Ealing Common", 319005 },
        { "Acton Town LT", 50000 },
        { "Chiswick Park LT", 54500 },
        { "Turnham Green LT", 73400 },
        { "Stamford Brook LT", 71300 },
        { "Ravenscourt Park LT", 68200 },
        { "Hammersmith LT", 59300 },
        { "Barons Court LT", 51600 },
        { "West Kensington", 76000 },
        { "Earls Court LT", 56200 },
        { "West Kensington LT", 76000 },
    });

    std::cout << "Ealing has NLC: " << station2nlc["Ealing Broadway"] << std::endl;
}
Angus Comber
  • 9,316
  • 14
  • 59
  • 107
  • @KonstantinosChalkias I did see that post but was in 2009 so I was hoping Java8 might add better support for this. – Angus Comber Dec 27 '15 at 19:13
  • 1
    Best answer is still the same - use one of guava helper classes. – Artur Biesiadowski Dec 27 '15 at 19:21
  • This post has the answers you expect (Java 8 and Guava) http://stackoverflow.com/questions/507602/how-can-i-initialize-a-static-map#answer-25829097 – Kostas Kryptos Dec 27 '15 at 19:23
  • Angus: What quality do you see in the C++ sample which is missing from the Java sample? LOC are the same. The C++ sample also has some costs for the temporary std::pair instances. – wero Dec 27 '15 at 19:33
  • @wero I was after a more natural way to create a hashmap from literals. The station2nlc.put line seems clumsy and does not initialise the hashmap in one operation. – Angus Comber Dec 27 '15 at 19:44

1 Answers1

1

Since you are using Java 8 you can use streams and collectors to achieve this.

import java.util.AbstractMap.SimpleEntry;
import java.util.stream.Collectors;
import java.util.stream.Stream;

...

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

It is pretty verbose but has a substantial advantage over the static initialisation method - the class which instantiates the map this way is not referenced by it. In the case of static initialisation the anonymous class created with new HashMap<>(){...} will hold a reference to the class that created it and the latter cannot be garbage collected until the map itself is.

Alla B
  • 656
  • 3
  • 9