在一条语句中一次将多个条目添加到HashMap


138

我需要初始化一个常量HashMap,并希望在一行语句中完成。避免这样的事情:

  hashMap.put("One", new Integer(1)); // adding value into HashMap
  hashMap.put("Two", new Integer(2));      
  hashMap.put("Three", new Integer(3));

类似于目标C:

[NSDictionary dictionaryWithObjectsAndKeys:
@"w",[NSNumber numberWithInt:1],
@"K",[NSNumber numberWithInt:2],
@"e",[NSNumber numberWithInt:4],
@"z",[NSNumber numberWithInt:5],
@"l",[NSNumber numberWithInt:6],
nil] 

看了这么多,我还没有找到任何显示如何做到这一点的例子。

Answers:


258

你可以这样做:

Map<String, Integer> hashMap = new HashMap<String, Integer>()
{{
     put("One", 1);
     put("Two", 2);
     put("Three", 3);
}};

11
@ user387184是的,他们称其为“双括号初始化程序”。请参见本主题:stackoverflow.com/questions/924285/...
Eng.Fouad

2
我只是将其放在代码中,并在以下行中收到此警告/消息:“可序列化类未声明类型为long的静态最终serialVersionUID字段”。我可以不理会吗?这是什么意思?谢谢
user387184

31
您不应该使用此方法。它为每一个使用它的时候,它有创建一个新的类不仅仅是说白了创建地图的表现更差。见stackoverflow.com/questions/924285/...
蒂莫Türschmann

7
我之所以对此表示反对,是因为它没有说明每次使用它都会创建一个新类。我认为人们应该意识到这样做的权衡。
idungotnosn

6
@TimoTürschmann似乎,如果我曾经需要像这样的静态初始化地图,那它也是静态的,从而消除了每次使用它的性能损失-您将受到一次罚款。我再也看不到有人希望这种初始化变量不是静态的(例如,有人会在循环中使用它吗?)。我可能是错的,程序员是有创造力的。
克里斯·西里菲斯

65

您可以使用Google Guava的ImmutableMap。只要您以后不关心修改地图(在使用此方法构造地图后就无法在地图上调用.put()),此方法就会起作用:

import com.google.common.collect.ImmutableMap;

// For up to five entries, use .of()
Map<String, Integer> littleMap = ImmutableMap.of(
    "One", Integer.valueOf(1),
    "Two", Integer.valueOf(2),
    "Three", Integer.valueOf(3)
);

// For more than five entries, use .builder()
Map<String, Integer> bigMap = ImmutableMap.<String, Integer>builder()
    .put("One", Integer.valueOf(1))
    .put("Two", Integer.valueOf(2))
    .put("Three", Integer.valueOf(3))
    .put("Four", Integer.valueOf(4))
    .put("Five", Integer.valueOf(5))
    .put("Six", Integer.valueOf(6))
    .build();

也可以看看: http //docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableMap.html

一个有点相关的问题:ImmutableMap.of()变通方法的HashMap的地图?


番石榴是巨大的,除非绝对必要,否则我不会在我的Android应用程序中使用它
-ericn

4
注意ImmutableMap不要接受null键或值。
Vadzim '17

@ericn ProGuard可让您排除未使用的库的任何部分。
dimo414 '18 -4-3

55

从Java 9开始,可以Map.of(...)像这样使用:

Map<String, Integer> immutableMap = Map.of("One", 1, 
                                           "Two", 2, 
                                           "Three", 3);

该地图是不可变的。如果要使地图可变,则必须添加:

Map<String, Integer> hashMap = new HashMap<>(immutableMap);

如果您不能使用Java 9,则必须自己编写类似的帮助程序方法,或者使用第三方库(例如Guava)为您添加该功能。


添加10个条目后,它引发奇怪的错误“无法解析方法”,此方法的错误吗?
vikramvi

2
@vikramvi是的,如果您看文档 Map.of最多只能完成10个条目,因为它非常费力
jolivier

8

Java没有地图文字,因此没有很好的方法来精确地执行您所要的内容。

如果需要那种语法,请考虑一些与Java兼容的Groovy并允许您这样做:

def map = [name:"Gromit", likes:"cheese", id:1234]

8

Maps在Java 9中还添加了工厂方法。最多10个条目。Maps具有重载的构造函数,这些构造函数使用键和值对。例如,我们可以按以下方式绘制各个城市及其人口的地图(根据Google在2016年10月发布的数据):

Map<String, Integer> cities = Map.of("Brussels", 1_139000, "Cardiff", 341_000);

Map的var-args情况要难一些,您需要同时具有键和值,但是在Java中,方法不能具有两个var-args参数。因此,一般情况是通过采用Map.Entry<K, V>对象的var-args方法并添加entry()构造它们的静态方法来处理的。例如:

Map<String, Integer> cities = Map.ofEntries(
    entry("Brussels", 1139000), 
    entry("Cardiff", 341000)
);

Java 9中的集合工厂方法


如果您可以使用Java 9+,那就太好了。这些工厂方法也返回不可变的映射。
Sourabh

6

这是一个简单的类,可以完成您想要的

import java.util.HashMap;

public class QuickHash extends HashMap<String,String> {
    public QuickHash(String...KeyValuePairs) {
        super(KeyValuePairs.length/2);
        for(int i=0;i<KeyValuePairs.length;i+=2)
            put(KeyValuePairs[i], KeyValuePairs[i+1]);
    }
}

然后使用它

Map<String, String> Foo=QuickHash(
    "a", "1",
    "b", "2"
);

这产生 {a:1, b:2}


4
    boolean x;
    for (x = false, 
        map.put("One", new Integer(1)), 
        map.put("Two", new Integer(2)),      
        map.put("Three", new Integer(3)); x;);

忽略声明x(这是避免“无法到达的语句”诊断所必需的),从技术上讲,它只是一个语句。


14
这真令人讨厌。
米卡楼梯

1
@MicahStairs-但这只是一个说法。
热门点击16-10-3

2
没错,但这是我从不希望在生产中偶然发现的那种代码。
米卡楼梯

@MicahStairs-我看得更糟。
热门点击16-10-3

1
天哪,我今天已经搜索了此代码,该代码如何工作?我已将其添加到测试代码中,但我无法弄清楚它在内部如何工作... :)
GOXR3PLUS,2016年

1

您可以将此实用程序功能添加到实用程序类中:

public static <K, V> Map<K, V> mapOf(Object... keyValues) {
    Map<K, V> map = new HashMap<>();

    for (int index = 0; index < keyValues.length / 2; index++) {
        map.put((K)keyValues[index * 2], (V)keyValues[index * 2 + 1]);
    }

    return map;
}

Map<Integer, String> map1 = YourClass.mapOf(1, "value1", 2, "value2");
Map<String, String> map2 = YourClass.mapOf("key1", "value1", "key2", "value2");

注意:Java 9可以使用Map.of


-1

另一种方法可能是编写特殊功能以通过正则表达式从一个字符串中提取所有元素值:

import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Example {
    public static void main (String[] args){
        HashMap<String,Integer> hashMapStringInteger = createHashMapStringIntegerInOneStat("'one' => '1', 'two' => '2' , 'three'=>'3'  ");

        System.out.println(hashMapStringInteger); // {one=1, two=2, three=3}
    }

    private static HashMap<String, Integer> createHashMapStringIntegerInOneStat(String str) {
        HashMap<String, Integer> returnVar = new HashMap<String, Integer>();

        String currentStr = str;
        Pattern pattern1 = Pattern.compile("^\\s*'([^']*)'\\s*=\\s*>\\s*'([^']*)'\\s*,?\\s*(.*)$");

        // Parse all elements in the given string.
        boolean thereIsMore = true;
        while (thereIsMore){
            Matcher matcher = pattern1.matcher(currentStr);
            if (matcher.find()) {
                returnVar.put(matcher.group(1),Integer.valueOf(matcher.group(2)));
                currentStr = matcher.group(3);
            }
            else{
                thereIsMore = false;
            }
        }

        // Validate that all elements in the given string were parsed properly
        if (currentStr.length() > 0){
            System.out.println("WARNING: Problematic string format. given String: " + str);
        }

        return returnVar;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.