有没有这样初始化Java HashMap的方法?:
Map<String,String> test =
new HashMap<String, String>{"test":"test","test":"test"};
正确的语法是什么?我没有发现任何与此相关的信息。这可能吗?我正在寻找最短/最快的方法来将一些“最终/静态”值放在地图中,这些值永远不会改变,并且在创建地图时预先知道。
有没有这样初始化Java HashMap的方法?:
Map<String,String> test =
new HashMap<String, String>{"test":"test","test":"test"};
正确的语法是什么?我没有发现任何与此相关的信息。这可能吗?我正在寻找最短/最快的方法来将一些“最终/静态”值放在地图中,这些值永远不会改变,并且在创建地图时预先知道。
当前回答
我们使用一个简单的实用程序类以流畅的方式初始化Maps:
Map<String, String> map = MapInit
.init("key1", "value1")
.put("key2", "value2")
.put("key3", "value3")
.getMap();
实用程序类不受键和值的类型、条目的数量以及生成的Map的类型的限制。
实用程序类如下所示:
public class MapInit<K, V, T extends Map<K, V>> {
private final T map;
private MapInit(final T map) {
this.map = map;
}
public T getMap() {
return this.map;
}
public static <K, V> MapInit<K, V, HashMap<K, V>> init(final K key, final V value) {
return init(HashMap::new, key, value);
}
public static <K, V, T extends Map<K, V>> MapInit<K, V, T> init(final Supplier<T> mapSupplier, final K key, final V value) {
return new MapInit<>(mapSupplier.get()) //
.put(key, value);
}
public MapInit<K, V, T> put(final K key, final V value) {
this.map.put(key, value);
return this;
}
}
其他回答
您可以创建一个方法来初始化映射,如下例所示:
Map<String, Integer> initializeMap()
{
Map<String, Integer> ret = new HashMap<>();
//populate ret
...
return ret;
}
//call
Map<String, Integer> map = initializeMap();
如果它是一个实例变量,那么一个实例初始化块绝对是最好的方法,特别是如果你不能使用Map.of(),因为你需要一个不同类型的映射。
但是,如果你感觉很活泼,你可以使用Java 8供应商(不推荐)。
private final Map<String,Runnable> games = ((Supplier<Map<String,Runnable>>)() -> {
Map<String,Runnable> map = new LinkedHashMap<>();
map.put("solarus",this::playSolarus);
map.put("lichess",this::playLichess);
return map;
}).get();
或者制作自己的功能界面(我觉得不错):
@FunctionalInterface
public interface MapMaker<M> {
static <M extends Map<K,V>,K,V> M make(M map,MapMaker<M> maker) {
maker.build(map);
return map;
}
void build(M map);
}
// Can use LinkedHashMap!
private final Map<String,Runnable> games = MapMaker.make(
new LinkedHashMap<>(),(map) -> {
map.put("solarus",this::playSolarus);
map.put("lichess",this::playLichess);
});
我们使用一个简单的实用程序类以流畅的方式初始化Maps:
Map<String, String> map = MapInit
.init("key1", "value1")
.put("key2", "value2")
.put("key3", "value3")
.getMap();
实用程序类不受键和值的类型、条目的数量以及生成的Map的类型的限制。
实用程序类如下所示:
public class MapInit<K, V, T extends Map<K, V>> {
private final T map;
private MapInit(final T map) {
this.map = map;
}
public T getMap() {
return this.map;
}
public static <K, V> MapInit<K, V, HashMap<K, V>> init(final K key, final V value) {
return init(HashMap::new, key, value);
}
public static <K, V, T extends Map<K, V>> MapInit<K, V, T> init(final Supplier<T> mapSupplier, final K key, final V value) {
return new MapInit<>(mapSupplier.get()) //
.put(key, value);
}
public MapInit<K, V, T> put(final K key, final V value) {
this.map.put(key, value);
return this;
}
}
of()似乎最普遍,也最不受限制。这里,它自动处理非对象输入值:
List<Map<String, Object> certs = new ArrayList<>(){{ add( Map.of(
"TAG", Obj1 // Object
"TAGGED_ID", 1L //Long
"DEGREE", "PARENT" // String
"DATE", LocalDate.now() // LocalDate
));}};
注意,由静态Map.of(..)构造函数创建的映射不允许键和值都为空。
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。