CollectorUtil { public static <T, C> Collector<T, ?, MapStream<C, List<T>>> groupBy(Function<T, C> grouper) { return Collector.of( () -> new GroupHolder<>(grouper), GroupHolder::add, GroupHolder::merge, GroupHolder::finisher ); } private  CollectorUtil(); static Collector<T, ?, MapStream<C, List<T>>> groupBy(Function<T, C> grouper);  }
@Test void groupBy() { final Map<Integer, List<String>> expected = new HashMap<>(); expected.put(1, Stream.of("A", "A").collect(toList())); expected.put(2, Collections.singletonList("BB")); final Map<Integer, List<String>> actual = Stream.of("A", "BB", "A").collect(collector).toMap(); assertEquals(expected, actual); }