1つのステートメントで複数のエントリをHashMapに一度に追加する


138

定数HashMapを初期化する必要があり、1行のステートメントでそれを実行したいと考えています。このようなsthの回避:

  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] 

私はこれをたくさん見た中で、これを行う方法を示す例を見つけていません。

回答:


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型の静的なfinal serialVersionUIDフィールドを宣言していません」。無視してもいいですか?これは何を意味するのでしょうか?ありがとう
user387184

31
このメソッドは使用しないでください。これは、使用するたびに新しいクラスを作成します。これは、単純にマップを作成するよりもパフォーマンスがはるかに劣ります。stackoverflow.com/questions/924285/…を
TimoTürschmann16年

7
私がこれに反対した理由は、使用するたびに新しいクラスが作成されることを説明しなかったためです。このようにすることのトレードオフを知っておくべきだと思います。
idungotnosn

6
@TimoTürschmann私がこのようなマップの静的な初期化が必要な場合、それも静的であり、使用するたびにパフォーマンスのペナルティ排除するようです -そのペナルティは1回しかありません。変数を静的にせずにこの種の初期化が必要になることは他にはありません(たとえば、ループでこれを使用する人はいますか?)。私は間違っているかもしれませんが、プログラマーは独創的です。
Chris Cirefice 2016年

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

やや関連する質問:マップでのHashMapのImmutableMap.of()の回避策?


グアバは巨大です。どうしても必要な場合を除いて、Androidアプリでは使用しません
ericn

4
キーや値をImmutableMap受け付けないことに注意してくださいnull
Vadzim

@ericn ProGuardを使用すると、使用していないライブラリの部分を除外できます。
dimo414

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

マップには、Java 9で追加されたファクトリメソッドもあります。最大10のエントリに対して、マップには、キーと値のペアを受け取るオーバーロードされたコンストラクタがあります。たとえば、さまざまな都市とその人口のマップを作成できます(2016年10月のgoogleによると)。

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

Mapのvar-argsの場合は少し難しく、キーと値の両方が必要ですが、Javaでは、メソッドに2つの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 2018年

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(「到達不能ステートメント」の診断を回避するために必要)を無視すると、技術的には1つのステートメントのみになります。


14
これはひどくハックです。
2016

1
@MicahStairs-しかし、それはたった1つのステートメントです。
Hot Licks

2
本当ですが、これは私が本番環境で偶然遭遇したくない種類のコードです。
2016

@MicahStairs-私はもっと悪いことを見てきました。
Hot Licks

1
今日はこれを検索しましたが、このコードはどのように機能しますか?テスト用にコードに追加しましたが、内部でどのように機能するかわかりません... :)
GOXR3PLUS

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

注:Map.ofJava 9を使用できます


-1

別のアプローチは、正規表現によって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;
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.