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

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

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


当前回答

使用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, Integer> initializeMap()
{
  Map<String, Integer> ret = new HashMap<>();

  //populate ret
  ...

  return ret;
}

//call
Map<String, Integer> map = initializeMap();

您可以在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

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

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

tl;博士

在Java 9和更高版本中使用Map.of…方法。

Map< String , String > animalSounds =
    Map.of(
        "dog"  , "bark" ,   // key , value
        "cat"  , "meow" ,   // key , value
        "bird" , "chirp"    // key , value
    )
;

地图of

Java9添加了一系列Map.of静态方法,以满足您的需要:使用文本语法实例化不可变的Map。

映射(条目集合)是不可变的,因此在实例化后不能添加或删除条目。此外,每个条目的键和值是不可变的,不能更改。有关其他规则,请参见Javadoc,例如不允许NULL,不允许重复键,映射的迭代顺序是任意的。

让我们看看这些方法,使用一些示例数据绘制一张一周中某一天的地图,以显示我们希望该天工作的人。

Person alice = new Person( "Alice" );
Person bob = new Person( "Bob" );
Person carol = new Person( "Carol" );

映射.of()

Map.of创建一个空的Map。无法修改,因此无法添加条目。下面是这样一个地图的示例,空的没有条目。

Map < DayOfWeek, Person > dailyWorkerEmpty = Map.of();

dailyWorkerEmpty.toString():{}

第页,共页(…)

Map.of(k,v,k,v…)是几个方法,需要1到10个键值对。下面是两个条目的示例。

Map < DayOfWeek, Person > weekendWorker = 
        Map.of( 
            DayOfWeek.SATURDAY , alice ,     // key , value
            DayOfWeek.SUNDAY , bob           // key , value
        )
;

weekendWorker.toString():{SUNDAY=人{name=“Bob”},星期六=人{name=“虱子”}}

项目地图(…)

条目的Map.Entries(Map.Entry,…)采用实现Map.Entrey接口的任意数量的对象。Java捆绑了两个实现该接口的类,一个是可变的,另一个是不可变的:AbstractMap.SimpleEntry,AbstractMap.SimpleModuleEntry。但是我们不需要指定具体的类。我们只需要调用Map.entry(k,v)方法,传递键和值,然后返回实现Map.entry接口的某个类的对象。

Map < DayOfWeek, Person > weekdayWorker = Map.ofEntries(
        Map.entry( DayOfWeek.MONDAY , alice ) ,            // Call to `Map.entry` method returns an object implementing `Map.Entry`. 
        Map.entry( DayOfWeek.TUESDAY , bob ) ,
        Map.entry( DayOfWeek.WEDNESDAY , bob ) ,
        Map.entry( DayOfWeek.THURSDAY , carol ) ,
        Map.entry( DayOfWeek.FRIDAY , carol )
);

weekdayWorker.toString():{星期三=人{name=‘Bob’},星期二=人{name=“Bob”},周四=人{name=‘Carol’}、星期五=人{name=‘Carol‘},周一=人{name=‘虱子’}

地图副本

Java10添加了Map.copyOf方法。传递现有的映射,获取该映射的不可变副本。

笔记

注意,不能保证通过Map.of生成的映射的迭代器顺序。条目具有任意顺序。不要根据看到的顺序编写代码,因为文档警告顺序可能会更改。

注意,所有这些Map.of…方法都返回未指定类的Map。底层的具体类甚至可能因Java的不同版本而异。这种匿名性使Java能够从各种实现中选择最适合您特定数据的实现。例如,如果您的键来自枚举,Java可能会在封面下使用EnumMap。

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