有没有这样初始化Java HashMap的方法?:

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

正确的语法是什么?我没有发现任何与此相关的信息。这可能吗?我正在寻找最短/最快的方法来将一些“最终/静态”值放在地图中,这些值永远不会改变,并且在创建地图时预先知道。


当前回答

我想对约翰尼·威勒的回答提出一个简短的警告。

Collectors.toMap依赖于Map.merge,不需要null值,因此它将抛出NullPointerException,如本错误报告中所述:https://bugs.openjdk.java.net/browse/JDK-8148463

此外,如果键出现多次,默认的Collectors.toMap将抛出IllegalStateException。

使用Java 8上的构建器语法获取具有空值的映射的另一种方法是编写一个由HashMap支持的自定义收集器(因为它确实允许空值):

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

其他回答

您可以通过两种简单的方式轻松地创建自己的Map.of(仅在Java9及更高版本中可用)方法

使用设定数量的参数

实例

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

使用列表制作

您也可以使用列表来实现这一点,而不是为某一组参数创建许多方法。

实例

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

笔记不建议将其用于所有对象,因为每次使用时都会生成一个匿名类。

如果只需要放置一个键值对,可以使用Collections.singletonMap(key,value);

使用Java 8或更低版本

您可以使用静态块用一些值初始化映射。例子:

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

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

使用Java 9或更高版本

在声明时,可以使用Map.of()方法用一些值初始化映射。例子:

public static Map<String,String> test = Map.of("test","test","test1","test");
Map<String,String> test = new HashMap<String, String>()
{
    {
        put(key1, value1);
        put(key2, value2);
    }
};

如果您允许第三方库,您可以使用Guava的ImmutableMap来实现字面上的简洁:

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

这最多适用于5个键/值对,否则您可以使用其生成器:

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

注意,Guava的ImmutableMap实现与Java的HashMap实现不同(最明显的是它是不可变的,不允许空键/值)有关更多信息,请参阅Guava关于其不可变集合类型的用户指南文章