背景
Java で Key と Value だけを持つデータが必要な場合は何を使いますか?Map でできないことはありません。が、あまりスマートなやり方でもありません。
Pair の実装が Java SE にない(わけではありませんが、あまり知られていません)ので、OSS を含めて調べてみました。
AbstractMap.SimpleEntry
実は 1.6 から標準に Pair の機能を提供する API がありました。Entry の実装です。名前が長ったらしいですね。
インスタンス作成
new AbstractMap.SimpleEntry(key, value)
キー・値の取り出し
Key は getKey() で、Value は getValue() で可能
値の変更
setValue メソッドで Value のみ変更可能
備考
AbstractMap には SimpleImmutableEntry というのもあります。こちらだと、setValue メソッドを実質無効にした、要素の変更が不可能な Entry を扱うことができます。setValue メソッドを呼び出すと UnsupportedOperationException が発生します。この実装はうれしいのでしょうか?
名前が長い件については、下記のようにラップしてやれば解決できます。
public class Pair<K, V> extends AbstractMap.SimpleEntry<K, V> {
/** serialVersionUID. */
private static final long serialVersionUID = 6411527075103472113L;
public Pair(final K key, final V value) {
super(key, value);
}
}
テストコード
javafx.util.Pair
JavaFX 2.0 以降のライブラリに含まれている Pair の実装です。上記の SimpleEntry とほぼ同じ使い方が可能です。ただし値を入れ替えることはできません。
テストコード
Pair (Eclipse Collections)
Eclipse Collections は昨年のクリスマスプレゼントです。Key と Value で別々の型を使いたい時はこちらを使います。
swap メソッドで Key と Value の入れ替えができるのが面白いです。
インスタンス作成
Tuples.pair(key, value)
キー・値の取り出し
Key は getOne() で、Value は getTwo() で可能
値の変更
不可、そもそもメソッドが存在しません。間違って呼び出して Exception が発生することもありません。
なお、putというメソッドが存在します。これは Pair に値を設定するのではなく、引数で渡した Map に Pair が持つ Key と Value を入れる、というメソッドです。引数で渡した Map が unmodifiable だと Exception が発生します。
ほか
swap メソッドで key と value を入れ替えた Pair を取得できます。
テストコード
Twin (Eclipse Collections)
Key と Value で同じ型の場合はこちらを用います。
インスタンス作成
Tuples.twin(key, value)
キー・値の取り出し
Key は getOne() で、Value は getTwo() で可能
値の変更
不可、そもそもメソッドが存在しません。間違って呼び出して Exception が発生することもありません。
なお、putというメソッドが存在するが、これは Twin に値を設定するのではなく、引数で渡した Map に Twin が持つ Key と Value を入れる、というメソッドです。引数で渡した Map が unmodifiable だと Exception が発生します。
ほか
swap メソッドで key と value を入れ替えた Twin を取得できます。
テストコード
org.apache.commons.lang3.tuple.Pair
Apache Commons Collections に用意されています。インスタンスを作るのにファクトリメソッドを使わせたり、MutableかImmutableか選べたり、
値の取り出し方に幅を持たせてあったりと、丁寧な作りをしています。
インスタンス作成
- Pair.of(key, value)
- MutablePair.of(key, value)
キー・値の取り出し
Key は getKey() か getLeft() で、Value は getValue() か getRight() で可能
値の変更
MutablePair は setValue() メソッドにより値だけ変更可能
Pair ないし ImmutablePair は変更不可、setValue() メソッドをコールすると UnsupportedOperationException が発生します。
テストコード
比較表
実装 | インスタンス作成 | 変更 | 値の取り出し |
---|---|---|---|
AbstractMap.SimpleEntry | new | ○ | getValue |
AbstractMap.SimpleImmutableEntry | new | × | getValue |
javafx.util.Pair | new | × | getValue |
Eclipse Collections Pair | Tuples.pair | × | getTwo |
Eclipse Collections Twin | Tuples.twin | × | getTwo |
Apache Commons Collections MutablePair | of | ○ | getValue/getRight |
Apache Commons Collections ImmutablePair | of | × | getValue/getRight |
まとめ
OSS の利用申請が面倒等の理由がなければ、Eclipse Collections か Apache Collections を使っておけばよさそうです。