Streamを使ったgroup化

まずは実際のソースコード
今回は(ちょっと古いが)「このマンガがすごい」をオブジェクトにしてみた。

       ComicRank cr1 = new ComicRank(2015, "こえのかたち", Genre.Men, 1);
        ComicRank cr2 = new ComicRank(2015, "魔法使いの嫁", Genre.Men, 2);
        ComicRank cr3 = new ComicRank(2015, "子供はわかってあげない", Genre.Men, 3);
        ComicRank cr4 = new ComicRank(2015, "ちーちゃんはちょっと足りない", Genre.Women, 1);
        ComicRank cr5 = new ComicRank(2014, "暗殺教室", Genre.Men, 1);
        ComicRank cr6 = new ComicRank(2014, "坂本ですが?", Genre.Men, 2);
        ComicRank cr7 = new ComicRank(2014, "亜人", Genre.Men, 3);
        ComicRank cr8 = new ComicRank(2014, "さよならソルシエ", Genre.Women, 1);
        ComicRank cr9 = new ComicRank(2014, "ときめきトゥナイト", Genre.Women, 2);

        List<ComicRank> list = new ArrayList<>();
        list.addAll(Arrays.asList(cr1, cr2, cr3, cr4, cr5, cr6, cr7, cr8, cr9));
        //リストを年ごとに名前でグループ化する
        Map<Integer, List<String>> yearsBookNameList = 
                list.stream()
                .collect(
                        Collectors.groupingBy(ComicRank::getYear, Collectors.mapping(ComicRank::getBookName, Collectors.toList())));
        
        System.out.println(yearsBookNameList);

結果

{2014=[暗殺教室, 坂本ですが?, 亜人, さよならソルシエ, ときめきトゥナイト], 2015=[こえのかたち, 魔法使いの嫁, 子供はわかってあげない, ちーちゃんはちょっと足りない]}

肝になるのはここ。 Collectors.groupingBy(ComicRank::getYear, Collectors.mapping(ComicRank::getBookName, Collectors.toList())));

何をしているのかというと、 groupingBy(arg1, arg2)というメソッドに、第一引数にはグループ化の基準となる値(この場合年)を渡し、
第2引数に、mapping()メソッドの結果となるCollectorを渡している。 んで、mappingには(マッピング関数、各要素が蓄積される型に変換するCollector)という形で使う。 今回はmapping(本の名前、リスト化)という具合。

では次に、各年の1位を{年:タイトル}(ジャンルは男のみ)で絞ってみる。

       //各年の、男編1位のコミック名を出す
        Comparator<ComicRank> byRank = Comparator.comparing(ComicRank::getRank);
        Map<Integer, Optional<ComicRank>> noOneMap =
        list.stream()
        .filter(o -> o.getGenre() == Genre.Men)
        .collect(groupingBy(ComicRank::getYear, reducing(BinaryOperator.minBy(byRank))));
        
        System.out.println(noOneMap);

結果

{2014=Optional[2014年1位:男編は[暗殺教室]], 2015=Optional[2015年1位:男編は[こえのかたち]]}