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

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

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


当前回答

您可以在Java 8中使用Streams(这是Set的示例):

@Test
public void whenInitializeUnmodifiableSetWithDoubleBrace_containsElements() {
    Set<String> countries = Stream.of("India", "USSR", "USA")
      .collect(collectingAndThen(toSet(), Collections::unmodifiableSet));

    assertTrue(countries.contains("India"));
}

裁判:https://www.baeldung.com/java-double-brace-initialization

其他回答

JAVA 8

在普通的java8中,您还可以使用Streams/Collectors来完成这项工作。

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

这具有不创建匿名类的优点。

请注意,进口产品包括:

import static java.util.stream.Collectors.toMap;
import java.util.AbstractMap.SimpleEntry;

当然,正如在其他答案中所指出的,在java9之后,您有更简单的方法来实现同样的目的。

所有版本

如果您恰好需要一个条目:Collections.singletonMap(“key”,“value”)。

对于Java版本9或更高版本:

是的,这现在是可能的。在Java 9中,添加了两种简化地图创建的工厂方法:

// this works for up to 10 elements:
Map<String, String> test1 = Map.of(
    "a", "b",
    "c", "d"
);

// this works for any number of elements:
import static java.util.Map.entry;    
Map<String, String> test2 = Map.ofEntries(
    entry("a", "b"),
    entry("c", "d")
);

在上面的示例中,test和test2都是相同的,只是表示Map的方式不同。Map.of方法最多为映射中的十个元素定义,而Map.ofEntries方法没有这样的限制。

注意,在这种情况下,生成的映射将是一个不可变的映射。如果希望映射是可变的,可以再次复制它,例如使用mutableMap=newHashMap<>(map.of(“a”,“b”));。还要注意,在这种情况下,键和值不能为空。

(另见JEP 269和Javadoc)

对于Java版本8之前的版本:

否,您必须手动添加所有元素。您可以在匿名子类中使用初始值设定项,使语法稍短:

Map<String, String> myMap = new HashMap<String, String>() {{
    put("a", "b");
    put("c", "d");
}};

然而,在某些情况下,匿名子类可能会引入不需要的行为。这包括例如:

它生成了一个额外的类,增加了内存消耗、磁盘空间消耗和启动时间在非静态方法的情况下:它保存对调用创建方法的对象的引用。这意味着当创建的映射对象仍然被引用时,不能对外部类的对象进行垃圾收集,从而阻塞了额外的内存

使用函数进行初始化也将使您能够在初始值设定项中生成映射,但避免了严重的副作用:

Map<String, String> myMap = createMap();

private static Map<String, String> createMap() {
    Map<String,String> myMap = new HashMap<String,String>();
    myMap.put("a", "b");
    myMap.put("c", "d");
    return myMap;
}

执行此操作的简单方法:

public static Map<String, String> mapWithValues(String...values) {
    Map<String, String> map = new HashMap<String, String>();
    
    for (int x = 0; x < values.length; x = x+2) {
        map.put(values[x], values[x+1]);
    }
    
    return map;
}

如果您允许第三方库,您可以使用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关于其不可变集合类型的用户指南文章

另一种方法是使用纯Java 7类和varargs:使用以下方法创建一个类HashMapBuilder:

public static HashMap<String, String> build(String... data){
    HashMap<String, String> result = new HashMap<String, String>();

    if(data.length % 2 != 0) 
        throw new IllegalArgumentException("Odd number of arguments");      

    String key = null;
    Integer step = -1;

    for(String value : data){
        step++;
        switch(step % 2){
        case 0: 
            if(value == null)
                throw new IllegalArgumentException("Null key value"); 
            key = value;
            continue;
        case 1:             
            result.put(key, value);
            break;
        }
    }

    return result;
}

使用如下方法:

HashMap<String,String> data = HashMapBuilder.build("key1","value1","key2","value2");