CUBは子供の白熊

Java SE 8 実践プログラミングの練習問題を解く

第2章 ストリーム API の使い方 : 問題 12, 13 : 並列ストリーム

問題 12

短い単語の数をカウントする処理

Stream<String> words = ~;
int[] shortWords = new int[12];
words.parallel()
    .forEach(s -> { if (s.length() < 12) shortWords[s.length()]++; });

は、競合が起こり正しくカウントできない。
shortWordsAtomicIntegerの配列に変えて、正しくカウントできるようにせよ

解答

AtomicInteger[] shortWords = new AtomicInteger[12];
Arrays.setAll(shortWords, n -> new AtomicInteger(0));
words.parallel()
    .forEach(s -> { if (s.length() < 12) shortWords[s.length()].getAndIncrement(); });
// カウント結果の表示
System.out.println(Arrays.toString(shortWords));

問題 13

上の解答で、次の点を変更せよ

  • 短い文字列はフィルターで取り出す
  • Collectors.groupingBy,Collectors.counting,collectメソッドを使用

解答

この場合、AtomicIntegerを使う必要はない。
そして配列ではなくMap<Integer, Long>に収集する。

Map<Integer, Long> wordsMap = words.parallel()
    .filter(s -> s.length() < 12)
    .collect(Collectors.groupingBy(String::length, Collectors.counting()));
// カウント結果の表示
for (int n = 0; n < 12; n++) {
    System.out.print(wordsMap.get(n));
    System.out.print(", ");
}