19

各エントリで groupBy を制限するにはどうすればよいですか?

例 (この例に基づく:ストリーム groupBy ):

studentClasses.add(new StudentClass("Kumar", 101, "Intro to Web"));
studentClasses.add(new StudentClass("White", 102, "Advanced Java"));
studentClasses.add(new StudentClass("Kumar", 101, "Intro to Cobol"));
studentClasses.add(new StudentClass("White", 101, "Intro to Web"));
studentClasses.add(new StudentClass("White", 102, "Advanced Web"));
studentClasses.add(new StudentClass("Sargent", 106, "Advanced Web"));
studentClasses.add(new StudentClass("Sargent", 103, "Advanced Web"));
studentClasses.add(new StudentClass("Sargent", 104, "Advanced Web"));
studentClasses.add(new StudentClass("Sargent", 105, "Advanced Web"));

このメソッドは単純なグループを返します:

   Map<String, List<StudentClass>> groupByTeachers = studentClasses
            .stream().collect(
                    Collectors.groupingBy(StudentClass::getTeacher));

返されるコレクションを制限したい場合はどうすればよいですか? すべての教師に最初の N クラスのみが必要であると仮定しましょう。どうすればそれができますか?

4

4 に答える 4

22

結果のリスト内の要素の数を制限する新しいコレクターを導入することは可能です。

このコレクターは、リストの先頭要素を保持します (遭遇順)。コレクション中に制限に達すると、アキュムレータとコンバイナはすべての要素を破棄します。コンバイナのコードは少し複雑ですが、これには追加の要素が追加されず、後で破棄されるだけであるという利点があります。

private static <T> Collector<T, ?, List<T>> limitingList(int limit) {
    return Collector.of(
                ArrayList::new, 
                (l, e) -> { if (l.size() < limit) l.add(e); }, 
                (l1, l2) -> {
                    l1.addAll(l2.subList(0, Math.min(l2.size(), Math.max(0, limit - l1.size()))));
                    return l1;
                }
           );
}

そして、次のように使用します。

Map<String, List<StudentClass>> groupByTeachers = 
       studentClasses.stream()
                     .collect(groupingBy(
                          StudentClass::getTeacher,
                          limitingList(2)
                     ));
于 2015-11-22T10:43:37.200 に答える
3

これにより、望ましい結果が得られますが、それでもストリームのすべての要素が分類されます。

final int N = 10;
final HashMap<String, List<StudentClass>> groupByTeachers = 
        studentClasses.stream().collect(
            groupingBy(StudentClass::getTeacher, HashMap::new,
                collectingAndThen(toList(), list -> list.subList(0, Math.min(list.size(), N)))));
于 2015-11-22T10:39:02.583 に答える