jen*_*ens 990 java collections dictionary initialization
有没有像这样初始化Java HashMap的方法?:
Map<String,String> test =
new HashMap<String, String>{"test":"test","test":"test"};
Run Code Online (Sandbox Code Playgroud)
什么是正确的语法?我没有发现任何有关此事的内容.这可能吗?我正在寻找最短/最快的方法,将一些"最终/静态"值放在一个永不改变的地图中,并在创建Map时提前知道.
yan*_*kee 1202
是的,现在可以了.在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:
Map<String, String> test2 = Map.ofEntries(
entry("a", "b"),
entry("c", "d")
);
Run Code Online (Sandbox Code Playgroud)
在以上两个例子test和test2将是相同的,只是表达地图的不同方式.该Map.of方法在地图中定义了最多十个元素,而该Map.ofEntries方法没有这样的限制.
请注意,在这种情况下,生成的地图将是不可变的地图.如果您希望地图是可变的,您可以再次复制它,例如使用mutableMap = new HashMap<>(Map.of("a", "b"));
不,您必须手动添加所有元素.您可以在匿名子类中使用初始化程序来使语法更短一些:
Map<String, String> myMap = new HashMap<String, String>() {{
put("a", "b");
put("c", "d");
}};
Run Code Online (Sandbox Code Playgroud)
但是,在某些情况下,匿名子类可能会引入不需要的行为.
使用函数进行初始化将执行相同的操作但可以提高代码的可读性:
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;
}
Run Code Online (Sandbox Code Playgroud)
gre*_*561 1020
这是一种方式.
HashMap<String, String> h = new HashMap<String, String>() {{
put("a","b");
}};
Run Code Online (Sandbox Code Playgroud)
但是,您应该小心并确保您理解上面的代码(它创建一个继承自HashMap的新类).因此,您应该在这里阅读更多内容: http ://www.c2.com/cgi/wiki?DoubleBraceInitialization,或者只是使用Guava:
Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
Run Code Online (Sandbox Code Playgroud)
Jen*_*ann 333
如果您允许第三方库,您可以使用Guava的ImmutableMap来实现类似文字的简洁:
Map<String, String> test = ImmutableMap.of("k1", "v1", "k2", "v2");
Run Code Online (Sandbox Code Playgroud)
Map<String, String> test = ImmutableMap.<String, String>builder()
.put("k1", "v1")
.put("k2", "v2")
...
.build();
Run Code Online (Sandbox Code Playgroud)
Paŭ*_*ann 103
没有直接的方法可以做到这一点 - Java没有Map文字(但我认为它们是针对Java 8提出的).
有些人喜欢这样:
Map<String,String> test = new HashMap<String, String>(){{
put("test","test"); put("test","test");}};
Run Code Online (Sandbox Code Playgroud)
这将创建一个HashMap的匿名子类,其实例初始化程序会放置这些值.(顺便说一句,地图不能包含两倍相同的值,你的第二个put会覆盖第一个.我会为下一个例子使用不同的值.)
正常的方式是这个(对于局部变量):
Map<String,String> test = new HashMap<String, String>();
test.put("test","test");
test.put("test1","test2");
Run Code Online (Sandbox Code Playgroud)
如果您的testmap是实例变量,请将初始化放在构造函数或实例初始值设定项中:
Map<String,String> test = new HashMap<String, String>();
{
test.put("test","test");
test.put("test1","test2");
}
Run Code Online (Sandbox Code Playgroud)
如果您的test映射是类变量,请将初始化放在静态初始化程序中:
static Map<String,String> test = new HashMap<String, String>();
static {
test.put("test","test");
test.put("test1","test2");
}
Run Code Online (Sandbox Code Playgroud)
如果您希望地图永远不会更改,则应在初始化后将地图包裹起来Collections.unmodifiableMap(...).您也可以在静态初始化程序中执行此操作:
static Map<String,String> test;
{
Map<String,String> temp = new HashMap<String, String>();
temp.put("test","test");
temp.put("test1","test2");
test = Collections.unmodifiableMap(temp);
}
Run Code Online (Sandbox Code Playgroud)
(我不确定你现在能否做出test决定......试试看并在这里报道.)
Sha*_*rog 61
Map<String,String> test = new HashMap<String, String>()
{
{
put(key1, value1);
put(key2, value2);
}
};
Run Code Online (Sandbox Code Playgroud)
小智 42
另一种方法是使用普通的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;
}
Run Code Online (Sandbox Code Playgroud)
使用这样的方法:
HashMap<String,String> data = HashMapBuilder.build("key1","value1","key2","value2");
Run Code Online (Sandbox Code Playgroud)
爪哇 8
在普通的 Java 8 中,您也可以使用它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));
Run Code Online (Sandbox Code Playgroud)
这具有不创建匿名类的优点。
请注意,进口是:
import static java.util.stream.Collectors.toMap;
import java.util.AbstractMap.SimpleEntry;
Run Code Online (Sandbox Code Playgroud)
当然,正如其他答案中所述,在 Java 9 之后,您可以使用更简单的方法来做同样的事情。
我想对约翰尼·威勒的回答提出一个简短的警告。
Collectors.toMap依赖Map.merge且不期望 null 值,因此它将抛出 a,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);
Run Code Online (Sandbox Code Playgroud)
使用Map.of…Java 9 及更高版本中的方法。
Map< String , String > animalSounds =
Map.of(
"dog" , "bark" , // key , value
"cat" , "meow" , // key , value
"bird" , "chirp" // key , value
)
;
Run Code Online (Sandbox Code Playgroud)
Map.ofJava 9 添加了一系列Map.of静态方法来做你想做的事:使用文字语法实例化一个不可变的Map。
映射(条目的集合)是不可变的,因此您无法在实例化后添加或删除条目。此外,每个条目的键和值是不可变的,无法更改。其他规则请参见 Javadoc,例如不允许 NULL,不允许重复键,映射的迭代顺序是任意的。
让我们看看这些方法,使用一些样本数据绘制一周中某天到我们期望在那天工作的人的地图。
Person alice = new Person( "Alice" );
Person bob = new Person( "Bob" );
Person carol = new Person( "Carol" );
Run Code Online (Sandbox Code Playgroud)
Map.of()Map.of创建一个空的Map. 不可修改,因此您无法添加条目。这是此类地图的示例,为空且没有条目。
Map < DayOfWeek, Person > dailyWorkerEmpty = Map.of();
Run Code Online (Sandbox Code Playgroud)
DailyWorkerEmpty.toString(): {}
Map.of( … )Map.of( k , v , k , v , …)有几种方法需要 1 到 10 个键值对。这是两个条目的示例。
Map < DayOfWeek, Person > weekendWorker =
Map.of(
DayOfWeek.SATURDAY , alice , // key , value
DayOfWeek.SUNDAY , bob // key , value
)
;
Run Code Online (Sandbox Code Playgroud)
weekendWorker.toString(): {SUNDAY=Person{ name='Bob' }, SATURDAY=Person{ name='Alice' }}
Map.ofEntries( … )Map.ofEntries( Map.Entry , … )接受任意数量的实现Map.Entry接口的对象。Java 捆绑了两个实现该接口的类,一个是可变的,另一个是不可变的: AbstractMap.SimpleEntry, AbstractMap.SimpleImmutableEntry. 但是我们不需要指定一个具体的类。我们只需要调用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 )
);
Run Code Online (Sandbox Code Playgroud)
weekdayWorker.toString(): {WEDNESDAY=Person{ name='Bob' }, TUESDAY=Person{ name='Bob' }, THURSDAY=Person{ name='Carol' }, FRIDAY=Person{ name='Carol' } , MONDAY=Person{ name='Alice' }}
Map.copyOfJava 10 添加了该方法Map.copyOf。传递现有地图,取回该地图的不可变副本。
注意,图的迭代顺序产生经由Map.of被不保证。条目具有任意顺序。不要根据看到的顺序编写代码,因为文档警告顺序可能会发生变化。
请注意,所有的这些Map.of…方法返回Map的未指定类别的。底层的具体类甚至可能因 Java 的一个版本而异。这种匿名性使 Java 能够从各种实现中进行选择,无论哪种最适合您的特定数据。例如,如果您的键来自enum,Java 可能会在幕后使用EnumMap。