Java gold 例題 ストリームAPI

次のコードの出力結果を答えてください
```java

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

public class ComputeTest {
	public static void main(String[] args) {
		String[] tokens = {
                "B", "5",
                "B", "4",
                "C", "10",
                "A", "8"
        };
		
		Map<String, Integer> voteCounts = new HashMap<>();
		
		for(int i = 0; i < tokens.length; i += 2) {
			String name = tokens[i];
			int votes = Integer.parseInt(tokens[i + 1]);
			voteCounts.compute(name, (key, oldValue) ->
					(oldValue == null) ? votes: oldValue + votes);
		}
				
		String topShareholder = voteCounts.entrySet().stream()
											.max(Map.Entry.comparingByValue())
											.map(Map.Entry::getKey)
											.orElse(null);
		
		Map<String, Integer> directorCounts = new HashMap<>();
        for (int i = 0; i < tokens.length; i += 2) {
            String name = tokens[i];
            directorCounts.compute(name, (key, oldValue) -> 
            			(oldValue == null) ? 1 : oldValue + 1 );
        }
		
		String topDirector = directorCounts.entrySet().stream()
											.max(Map.Entry.comparingByValue())
											.map(Map.Entry::getKey)
											.orElse(null);
		
		System.out.print(topShareholder);
		System.out.print(topDirector);
	}

    //default V compute​(K key, BiFunction<? super K,​? super V,​? extends V> remappingFunction)
    //指定されたキーと現在マップされている値に対するマッピングの計算を試みます(現在のマッピングが存在しない場合はnull)。
}
```

1. AB
1. ABC
1. BC
1. CB
1. CBA
1. 8910
1. 1098

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

解答 
4    CB

解説

このコードは、文字と数字のリストから以下の2点を見つけ出します。
・最も数字の合計が大きい文字
・最も選ばれた回数の多い文字
　

・`Map.compute`を使って、キーが存在しない場合の初期化や、既存の値への操作を行います。


マップの初期化と集計
```java
Map<String, Integer> voteCounts = new HashMap<>();
for(int i = 0; i < tokens.length; i += 2) {
    String name = tokens[i];
    int votes = Integer.parseInt(tokens[i + 1]);
    voteCounts.compute(name, (key, oldValue) ->
        (oldValue == null) ? votes : oldValue + votes);
```
・`voteCounts`は文字（"A" "B" "C")ごとの数字を記録するための`Map`です。
・`for`ループを使用して、`tokens`配列の要素を２つずつ処理します。１つ目の要素は文字、２つ目の要素は数字です。文字列の1をint型に変換するには`Integer.parseInt("1");`を利用します。
・`compute`メソッドを使用して、マップに文字が存在しない場合、その文字に初期の数字を設定します。既に存在する場合は、既存の数字に新たな数字を加算します。

最も数字の大きい文字を見つける
```java
String topShareholder = voteCouts.entrySet().stream()
                         .max(Map.Entry.comparingByValue())
                         .map(Map.Entry::getKey)
                         .orElse(null);
```
・`entrySet()`メソッドを使用して`voteCounts`のすべてのエントリを取得し、`Stream`に変換します。
・`max`メソッドと`Map.Entry.comparingByValue()`を使用して、数字が最も多い文字を見つけます。
・`map(Map.Entry::getKey)`でエントリのキー(文字)を取得し、結果が存在しない場合は`orElse(null)`で`null`を返します。

`directorCounts` マップの初期化と選ばれた回数の集計
```java
Map<String, Integer> directorCounts = new HashMap<>();
for(int i = 0; i < tokens.length; i += 2) {
    String name = tokens[i];
    directorCounts.compute(name, (key, oldValue) ->
        (oldValue == null) ? 1 : oldValue + 1);
```
・`directorCounts`は、各文字が選ばれた回数を記録するための`Map`です。
・`compute`メソッドを使って、文字が存在しない場合は初期値として1を設定し、既に存在する場合は既存の回数に1を加算します。

 最も多く選ばれた文字を見つける
```java
String topDirector = directorCounts.entrySet().stream()
                        .max(Map.Entry.comparingByValue())
                        .map(Map.Entry::getKey)
                        .orElse(null);
```
・`directorCounts`のエントリを`Stream`に変換し、選出回数が最も多い文字を見つけます。
`map(Map.Entry::getKey)`でエントリのキーを取得し、結果が存在しない場合は`orElse(null)`で`null`を返します。


結果の出力
```java
System.out.print(topShareholder);
System.out.print(topDirector);

//出力結果: CB
```
・最後に、最も数字の多い文字と、最も多く選ばれた文字を出力します。

---

https://qiita.com/T-ngtj/private/df254aacd05be698199a