0

Good day all,
Considering the following code example:

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

    public class StaticPractice {
    
        private final Map<String, String> mapperMap;
    
        public StaticPractice(){
            mapperMap = new HashMap<String, String>(); 
            mapperMap.put("Foo1", "Bar1");
            mapperMap.put("Foo2", "Bar1");
            mapperMap.put("Foo3", "Bar2");
            mapperMap.put("Foo3", "Bar3");
            //...
            mapperMap.put("MoreFoo", "BarAgain");
        }
     
        public void doSomething(){
            //use mapperMap    
       }
    }

I am looking for a more succinct way of creating a Map data structure that has a whole lot of constant Strings mapping to a whole lot of other constant Strings. In use, the example is far from "clean" or elegant, and is very verbose (there are alot of predefined constant mappings).

The goal of the class is to map objects referenced by these predefined constant Strings. It is commonplace in my particular code convention to use private static final String for all String constant, this example as well breaks that convention.

Would greatly appreciate any input, the wealth of knowledge from SO contributors always humbles me.
Much thanks.

Edit: Requirement specifies no external files.

2
  • If the number of mappings is constant then may be you could consider creating an enum instead. Also you can't really add Foo3 more than once, the last one replaces the existing one. Commented Apr 22, 2014 at 3:28
  • @BheshGurung You can add Foo3 more than once, just the last one replaces the first, as you noted :) Commented Apr 22, 2014 at 3:36

4 Answers 4

3

One approach would be to create a builder class that generates the map. This has the advantage that you can optimize for concise syntax. You can also do things like making the generated map immutable -- useful if you want to use it as a publically accessible constant.

In your example, I notice that you have more than one key mapping to the same value. So, it would be more concise to have a method that takes a value followed by a list of keys. You can also make it more concise by having the builder return itself so that you can "chain" method calls:

class Builder<K,V> {
   final Map<K,V> map = new HashMap<K,V>();

   Builder add(V value, K... keys) {
      for(K key : keys) {
         map.put(key, value);
      }
      return this;
   }

   Map<K,V> build() {
      return Collections.unmodifiableMap(new HashMap<K,V>(map));
   }
}

// Usage:
mapperMap = new Builder<String,String>()
   .add("Bar1", "Foo1", "Foo2")
   .add("Bar2", "Foo3")
   ...
   .build();

Alternately you might take a look at the Guava ImmutableMap class, which has a builder using the chaining syntax, though it doesn't have a way to map multiple keys to a single value in one call.

Sign up to request clarification or add additional context in comments.

2 Comments

Any reason you create a HashMap wrapper before passing into unmoifiableMap()? Are you worried about subsequent use of a transient builder object?
@Paul: Yes, I wanted to ensure that calling add() after build() wouldn't modify the already-built map.
2

I Think you can try using Properties instead of map or initializing the map by reading strings from a configration file.

1 Comment

Thank you for the input, I will upvote you for the contribution. The requirement makes it necessary to not use external files.
1

The most succint way I know is to define your map as an anonymous subclass of HashMap with an instance initializer:

private final Map<String, String> mapperMap =
  Collections.unmodifiableMap(new HashMap() {{ // instance initializer
    put("Foo1", "Bar1");
    put("Foo2", "Bar1");
    put("Foo3", "Bar2");
    put("Foo3", "Bar3");
}});

Comments

0

If you want it to be a final String, you can always create a class with a couple of constant strings and the use a list of objects of that class.

You can do it like this:

class MapClass {
    private static final String key;
    private static final String value;
}

List<MapClass> l = new ArrayList<>();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.