Skip to content

Instantly share code, notes, and snippets.

@gakuzzzz
Last active September 17, 2020 09:12
Show Gist options
  • Save gakuzzzz/0062da09abfd4c8bf4b1346d409d2bf7 to your computer and use it in GitHub Desktop.
Save gakuzzzz/0062da09abfd4c8bf4b1346d409d2bf7 to your computer and use it in GitHub Desktop.
LinkedHashMapの初期化

https://twitter.com/cero_t/status/1305994285897011200 の話。

Map.of

Map<String, Integer> someKeyName2ValueName = new LinkedHashMap<>(Map.of(
    "foo", 10,
    "bar", 20,
    "baz", 30
));

順序を保持する必要があるので Map.of をコンストラクタに渡す手は残念ながら使えません。

無名サブクラス

Map<String, Integer> someKeyName2ValueName = new LinkedHashMap<>() {{
    put("foo", 10);
    put("bar", 20);
    put("baz", 30);
}};

たまにこのイディオムを見かけますが、これをインスタンススコープで行うと、 someKeyName2ValueName に代入されたMapインスタンスがエンクロージングクラスのインスタンス参照を保持してしまうので、 メモリリークや直列化で問題が発生したりします。

put 連打

Map<String, Integer> someKeyName2ValueName = new LinkedHashMap<>();
someKeyName2ValueName.put("foo", 10);
someKeyName2ValueName.put("bar", 20);
someKeyName2ValueName.put("baz", 30);

一番王道だと思われます。スコープが区切れないのと変数名が長いとうざったいというのはありますね。

ブロックを用いてこの辺軽減する手もあったりします。

Map<String, Integer> someKeyName2ValueName;
{
    var m = new LinkedHashMap<String, Integer>();
    m.put("foo", 10);
    m.put("bar", 20);
    m.put("baz", 30);
    someKeyName2ValueName = m;
}

tap の導入

public static <A> A tap(A a, Consumer<? super A> f) {
    f.accept(a);
    return a;
}

こういうメソッドをユーティリティとして用意しておくと以下のように書けます。

Map<String, Integer> someKeyName2ValueName = tap(new LinkedHashMap<>(), m -> {
    m.put("foo", 10);
    m.put("bar", 20);
    m.put("baz", 30);
});

Kotlin や Scala には標準で用意されてるので便利ですね。(それらの言語の場合はそもそも別のより良い方法がありますが)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment