Skip to content

Instantly share code, notes, and snippets.

@gakuzzzz

gakuzzzz/_0.md

Last active Sep 17, 2020
Embed
What would you like to do?
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
You can’t perform that action at this time.