Java8でListとかMapに追加されたメソッドをいくつか試してみる

API ドキュメントを眺めて目についたメソッドを試してみる。

Map が色々追加されている。

#環境
##Java
1.8.0

#Collection
##removeIf(Predicate<? super E> filter)
```java:
package java8;

import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("hoge", "fuga", "piyo");
        
        System.out.println("before : " + list);
        list.removeIf(str -> str.contains("g"));
        System.out.println("after : " + list);
    }
}
```

```text:実行結果
before : [hoge, fuga, piyo]
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.remove(AbstractList.java:161)
	at java.util.AbstractList$Itr.remove(AbstractList.java:374)
	at java.util.Collection.removeIf(Collection.java:415)
	at java8.Main.main(Main.java:12)
Java Result: 1
```

( ´ﾟωﾟ)・;'.、ﾌﾞｯ

気を取り直して。。。

```java:
package java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>(Arrays.asList("hoge", "fuga", "piyo"));
        
        System.out.println("before : " + list);
        list.removeIf(str -> str.contains("g"));
        System.out.println("after : " + list);
    }
}
```

```text:
before : [hoge, fuga, piyo]
after : [piyo]
```

`Collection` インターフェースに追加されたデフォルト実装。

各要素に対して `filter` で指定した関数を実行して、 true を返した要素を削除する。
要素が削除された場合は、 true を返却し、１つも削除されない場合は false を返す。

#List
##replaceAll(UnaryOperator<E> operator)
```java:
package java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>(Arrays.asList("hoge", "fuga", "piyo"));
        
        System.out.println("before : " + list);
        list.replaceAll(str -> str.toUpperCase());
        System.out.println("after : " + list);
    }
}
```

```text:実行結果
before : [hoge, fuga, piyo]
after : [HOGE, FUGA, PIYO]
```

リストの各要素に対して `operator` を適用して、 `operator` が返した値をリストにセットし直す。

##sort(Comparator<? super E> c)
```java:
package java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>(Arrays.asList("hoge", "fuga", "piyo"));
        
        System.out.println("before : " + list);
        list.sort((s1, s2) -> s1.compareTo(s2));
        System.out.println("after : " + list);
    }
}
```

```text:実行結果
before : [hoge, fuga, piyo]
after : [fuga, hoge, piyo]
```

リストを指定した `Comparator` を使ってソートする。
デフォルトの実装は `Collections.sort(List<T> list, Comparator<? super T> c)` を使う。

#Map
##compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
```java:
package java8;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
        
        System.out.println("before : " + map);
        map.compute("hoge", (key, old) -> "<" + old + ">");
        map.compute("fuga", (key, old) -> null);
        map.compute("fizz", (key, old) -> "FIZZ");
        System.out.println("after : " + map);
    }
}
```

```text:実行結果
before : {hoge=HOGE, fuga=FUGA, piyo=PIYO}
after : {hoge=<HOGE>, piyo=PIYO, fizz=FIZZ}
```

第一引数で渡した `key` でマップを検索し、そのキーと取得した値を第二引数で指定した `remappingFunction` に渡す。

`remappingFunction` が null 以外の値を返した場合は、マップの中身をその値で置き換える。
`remappingFunction` が null を返した場合、そのキーのエントリは削除される。

##computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
```java:
package java8;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
        
        System.out.println("before : " + map);
        map.computeIfAbsent("hoge", (key) -> null /*ここは実行されない*/);
        map.computeIfAbsent("fizz", (key) -> "FIZZ");
        System.out.println("after : " + map);
    }
}
```

```text:実行結果
before : {hoge=HOGE, fuga=FUGA, piyo=PIYO}
after : {hoge=HOGE, fuga=FUGA, piyo=PIYO, fizz=FIZZ}
```

`key` で指定したキーでマップを検索した結果が null の場合、第二引数で指定した `mappingFunction` が実行される。

`mappingFunction` が null 以外の値を返した場合、そのときのキーと値がマップに追加される。

デフォルトの実装は同期されないので、マルチスレッド使うときは注意。
`ConcurrentHashMap` の `computeIfAbsent()` は同期するようにデフォルトメソッドをオーバーライドしており、そのことが API ドキュメントに明記されている。

##computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
```java:
package java8;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
        
        System.out.println("before : " + map);
        map.computeIfPresent("hoge", (key, old) -> "<" + old + ">");
        map.computeIfPresent("fuga", (key, old) -> null);
        map.computeIfPresent("fizz", (key, old) -> "FIZZ" /*ここは実行されない*/);
        System.out.println("after : " + map);
    }
}
```

```text:実行結果
before : {hoge=HOGE, fuga=FUGA, piyo=PIYO}
after : {hoge=<HOGE>, piyo=PIYO}
```

`key` で指定した値でマップを検索して、 null 以外の値を返した場合は `remappingFunction` を実行する。

`remappingFunction` が null 以外の値を返した場合は、マップの中身をその値で置き換える。
`remappingFunction` が null を返した場合、そのキーのエントリは削除される。

##forEach(BiConsumer<? super K,? super V> action)
```java:
package java8;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
        
        map.forEach((key, value) -> System.out.printf("key=%s, value=%s%n", key, value));
    }
}
```

```text:実行結果
key=hoge, value=HOGE
key=fuga, value=FUGA
key=piyo, value=PIYO
```

マップのエントリを走査して、 `action` にキーと値を渡す。

##getOrDefault(Object key, V defaultValue)
```java:
package java8;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
        
        System.out.printf("map[hoge] = %s%n", map.getOrDefault("hoge", "AAA"));
        System.out.printf("map[fizz] = %s%n", map.getOrDefault("fizz", "default value"));
    }
}
```

```text:実行結果
map[hoge] = HOGE
map[fizz] = default value
```

`key` で指定したエントリがマップに存在しない場合、 `defaultValue` で指定した値を返す。

マップに存在するかどうかは、 `containsKey()` を使っている。

##merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
```java:
package java8;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        
        System.out.println("before : " + map);
        
        for (int i=0; i<4; i++) {
            StringBuilder sb = new StringBuilder(i + " : ");
            
            map.merge("hoge", 0, (oldValue, value) -> {
                sb.append("oldValue=").append(oldValue).append(", value=").append(value);
                return oldValue + 1;
            });
            
            System.out.println(sb);
        }
        
        System.out.println("after : " + map);
    }
}
```

```text:実行結果
before : {}
0 : 
1 : oldValue=0, value=0
2 : oldValue=1, value=0
3 : oldValue=2, value=0
after : {hoge=3}
```

指定したキーがマップに存在しない場合は第二引数の値をセットする。
既にマップに存在する場合は、第三引数で指定した関数を実行して、その戻り値をセットする。

詳細なロジックは以下。

1. `key` で指定した値でマップを検索する。
1. 検索した結果が null の場合は、 `value` で指定した値を取得する。
1. 検索した結果が null でない場合は、 `remappingFunction` を実行し、その戻り値を取得する。
1. 取得した値（`value` か `remappingFunction` の戻り値）が null の場合は、 `key` に紐づくエントリを削除する。
1. null でない場合は、取得した値でエントリの値を上書きする。

##remove(Object key, value)
```java:
package java8;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
        
        System.out.println("before : " + map);
        map.remove("hoge", "HOGE");
        map.remove("fuga", "****");
        map.remove("****", "PIYO");
        System.out.println("after : " + map);
    }
}
```

```text:実行結果
before : {hoge=HOGE, fuga=FUGA, piyo=PIYO}
after : {fuga=FUGA, piyo=PIYO}
```

`key` と `value` で指定した組み合わせのエントリーがマップに存在する場合に限り、そのエントリを削除する。

##replace(K key, oldValue, newValue)
```java:
package java8;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
        
        System.out.println("before : " + map);
        map.replace("hoge", "HOGE", "REPLACE");
        map.replace("fuga", "****", "NO REPLACE");
        map.replace("****", "PIYO", "NO REPLACE");
        System.out.println("after : " + map);
    }
}
```

```text:実行結果
before : {hoge=HOGE, fuga=FUGA, piyo=PIYO}
after : {hoge=REPLACE, fuga=FUGA, piyo=PIYO}
```

`key` と `oldValue` で指定した組み合わせのエントリーがマップに存在する場合に限り、そのエントリの値を `newValue` で書き換える。

##replace(K key, V value)
```java:
package java8;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
        
        System.out.println("before : " + map);
        map.replace("hoge", "REPLACE");
        map.replace("****", "NO REPLACE");
        System.out.println("after : " + map);
    }
}
```

```text:実行結果
before : {hoge=HOGE, fuga=FUGA, piyo=PIYO}
after : {hoge=REPLACE, fuga=FUGA, piyo=PIYO}
```

`key` で指定したエントリがマップに存在する場合、そのエントリの値を `value` で指定した値で置き換える。

エントリが存在するかどうかには `containsKey()` が使用される。





#参考
- [Java Platform SE 8](http://download.java.net/jdk8/docs/api/)