Java8で追加されたAPI Map編 その1

【前提条件】

[環境]
[参考資料]

Java8 APIドキュメント
http://docs.oracle.com/javase/jp/8/api/

【概要】

今回はMapクラスに追加されたメソッドを調べてみました。

【getOrDefaultメソッド】

Map#getOrDefaultメソッドは指定したキーのエントリがなかった場合に
デフォルトの値を返すと言うメソッドです。

[サンプルコード]
    private static void getOrDefaultSample() {
        final Map<Integer, String> mapValue = new HashMap<>();

        mapValue.put(1, "one");
        mapValue.put(2, "two");
        mapValue.put(3, "three");
        mapValue.put(4, null);

        System.out.println(mapValue.getOrDefault(1, "default!"));
        System.out.println(mapValue.getOrDefault(4, "default!"));
        System.out.println(mapValue.getOrDefault(5, "default!"));
    }

Map#getOrDefaultメソッドのパラメータは
1つ目がキー値、2つ目がデフォルト値を指定します。

[実行結果]
one
null
default!

指定したキーのエントリがある場合はそのエントリの値が返却されます。
エントリの値がNullだった場合はNullが返却されます。

指定してキーのエントリがない場合はMap#getOrDefaultメソッドで指定した
デフォルト値が返却されます。

【putIfAbsentメソッド】

Map#putIfAbsentメソッドは指定したキーのエントリに紐付く値が
Nullだった値を設定すると言うメソッドです。

[サンプルコード]
    private static void putIfAbsentSample() {
        
        final Map<Integer, String> mapValue = new HashMap<>();

        mapValue.put(1, "one");
        mapValue.put(2, "two");
        mapValue.put(3, "three");
        mapValue.put(4, null);

        System.out.println("====================== before ======================");
        mapValue.entrySet().stream().forEach(System.out::println);

        mapValue.putIfAbsent(1, "ichi");
        mapValue.putIfAbsent(4, "four");
        mapValue.putIfAbsent(5, "five");
        System.out.println("====================== after ======================");
        mapValue.entrySet().stream().forEach(System.out::println);
    }

Map#putIfAbsentメソッドのパラメータは
1つ目がキー値、2つ目が設定したい値を指定します。

[実行結果]
====================== before ======================
1=one
2=two
3=three
4=null
====================== after ======================
1=one
2=two
3=three
4=four
5=five

キー値が「1」のエントリは値が反映されていません。
Map#putIfAbsentメソッドは値がNullだった場合に値が反映されるため、
すでに値が設定されていたキー値「1」に関しては影響がありません。

キー値が「4」と「5」のエントリは値が反映されています。
反映されるパターンとしては下記の2パターンです。

  • キー値が存在して値がNullの場合
  • キー値が存在していない場合

【removeメソッド】

厳密に言うとMap#removeメソッドは存在していたのですが、
Java8から新しいシグネチャが追加されています。

[サンプルコード]
    private static void removeSample() {
        
        final Map<Integer, String> mapValue = new HashMap<>();

        mapValue.put(1, "one");
        mapValue.put(2, "two");
        mapValue.put(3, "three");
        mapValue.put(4, "four");

        mapValue.remove(4, "default");
        System.out.println("====================== not match ======================");
        mapValue.entrySet().stream().forEach(System.out::println);

        mapValue.remove(4, "four");
        System.out.println("====================== match ======================");
        mapValue.entrySet().stream().forEach(System.out::println);
    }

Map#removeメソッドでパラメータが1つのものは過去のバージョンにもありました。
Java8からはパラメータが2つのものが追加されています。

パラメータが2つのものはエントリのキーと値を渡します。
キーと値が一致している場合にのみ削除されます。

[実行結果]
====================== not match ======================
1=one
2=two
3=three
4=four
====================== match ======================
1=one
2=two
3=three

最初にMap#removeメソッドを実行した時には
キーはあるもののエントリの値が一致していないため削除されていません。

キーと値が一致した場合にのみ削除されます。

【replaceメソッド】

Mapクラスにもreplaceメソッドが追加されました。

[サンプルコード]
    private static void replaceSample() {
        
        final Map<Integer, String> mapValue = new HashMap<>();

        mapValue.put(1, "one");
        mapValue.put(2, "two");
        mapValue.put(3, "three");

        mapValue.replace(1, "ichi");
        System.out.println("====================== one => ichi ======================");
        mapValue.entrySet().stream().forEach(System.out::println);

        mapValue.replace(1, "iti", "one");
        System.out.println("====================== not match ======================");
        mapValue.entrySet().stream().forEach(System.out::println);

        mapValue.replace(1, "ichi", "one");
        System.out.println("====================== match ======================");
        mapValue.entrySet().stream().forEach(System.out::println);
    }

Map#replaceメソッドシグネチャは下記の2つがあります。

  • replace(K key, V value)
  • replace(K key, V oldValue, V newValue)

keyは置き換えをする対象のキーです。

key,valueを指定している場合は一致するキーがあれば値を置き換えます。

key,oldValue,newValueを指定している場合は
key-oldValueの組み合わせに一致するエントリがあれば値を置き換えます。

[実行結果]
====================== one => ichi ======================
1=ichi
2=two
3=three
====================== not match ======================
1=ichi
2=two
3=three
====================== match ======================
1=one
2=two
3=three

最初に「one」が「ichi」に置き換えられます。

2回目は「キー:1,値:iti」に一致するエントリがないため、
値が置き換えられません。

3回目は「キー:1,値:ichi」に一致するエントリがあるため、
値が置き換えられます。

【replaceAllメソッド】

Map#replaceAllメソッドはMapオブジェクトの全ての値を置き換えます。
パラメータは関数オブジェクトなので、
特定の条件を満たす場合にのみ置き換えると言うコードもかけます。

[サンプルコード]
    private static void replaceAllSample() {
        
        final Map<Integer, String> mapValue = new HashMap<>();

        mapValue.put(1, "one");
        mapValue.put(2, "two");
        mapValue.put(3, "three");

        mapValue.replaceAll(
                (key, value) -> {
                    if(2 <= key) {
                        return "replaced";
                    }

                    return value;
                });
        mapValue.entrySet().stream().forEach(System.out::println);
    }

Map#replaceAllのパラメータはBiFunctionオブジェクトです。
キーと値のオブジェクトを受け取り、値と同じ型の結果を返却する
BiFunctionオブジェクトです。

サンプルではキー値が2以上の場合は置き換えるようにして、
2未満はvalue値をそのまま返却しています。

[実行結果]
1=one
2=replaced
3=replaced

キーが2以上のものが「replaced」に置き換わっていることがわかります。

【まとめ】

今回は下記のメソッドを調べました。

  • getOrDefault
  • putIfAbsent
  • remove
  • replace
  • replaceAll

getOrDefaultメソッドとputIfAbsentメソッドは
値が取得できない場合の挙動に関するメソッドなので、
追加されたメソッドの中では多用されるのではないでしょうか?

putIfAbsentメソッドに関しては
初期値を設定する場合に便利そうです。