How can I initialise a static Map?

前端 未结 30 1005
慢半拍i
慢半拍i 2020-11-22 08:43

How would you initialise a static Map in Java?

Method one: static initialiser
Method two: instance initialiser (anonymous subclass) or some other m

相关标签:
30条回答
  • 2020-11-22 09:31

    I've read the answers and i decided to write my own map builder. Feel free to copy-paste and enjoy.

    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> mapOf(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: Lately, I keep finding public static method of pretty often and I kinda like it. I added it into the code and made the constructor private, thus switching to static factory method pattern.

    EDIT2: Even more recently, I no longer like static method called of, as it looks pretty bad when using static imports. I renamed it to mapOf instead, making it more suitable for static imports.

    0 讨论(0)
  • 2020-11-22 09:34

    I would use:

    public class Test {
        private static final Map<Integer, String> MY_MAP = createMap();
    
        private static Map<Integer, String> createMap() {
            Map<Integer, String> result = new HashMap<>();
            result.put(1, "one");
            result.put(2, "two");
            return Collections.unmodifiableMap(result);
        }
    }
    
    1. it avoids an anonymous class, which I personally consider to be a bad style, and avoid
    2. it makes the creation of map more explicit
    3. it makes map unmodifiable
    4. as MY_MAP is constant, I would name it like constant
    0 讨论(0)
  • 2020-11-22 09:34

    Well... I like enums ;)

    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 ) );
    }
    
    0 讨论(0)
  • 2020-11-22 09:35

    The instance initialiser is just syntactic sugar in this case, right? I don't see why you need an extra anonymous class just to initialize. And it won't work if the class being created is final.

    You can create an immutable map using a static initialiser too:

    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);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 09:36
    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);
        }
    }
    

    If we declare more than one constant then that code will be written in static block and that is hard to maintain in future. So it is better to use anonymous class.

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

    And it is suggested to used unmodifiableMap for constants other wise it can't be treated as constant.

    0 讨论(0)
  • 2020-11-22 09:36

    JEP 269 provides some convenience factory methods for Collections API. This factory methods are not in current Java version, which is 8, but are planned for Java 9 release.

    For Map there are two factory methods: of and ofEntries. Using of, you can pass alternating key/value pairs. For example, in order to create a Map like {age: 27, major: cs}:

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

    Currently there are ten overloaded versions for of, so you can create a map containing ten key/value pairs. If you don't like this limitation or alternating key/values, you can use ofEntries:

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

    Both of and ofEntries will return an immutable Map, so you can't change their elements after construction. You can try out these features using JDK 9 Early Access.

    0 讨论(0)
提交回复
热议问题