[TOC]
声明
这一系列文章旨在帮助大家理解 Collector
的执行流程,至于实现的是否高效、是否优雅、是否合理等暂且不论。
现在来实现一个和 java.util.stream.Collectors#groupingBy()
一样效果的 GroupByCollector
。
当然此处的实现肯定没有jdk那样灵活,效率就先不提了,至少贫道的这个实现不支持多级分组V_V。
若对 Collector
的各个流程有疑问请移驾此处:
简单实现
// 这个是从jdk8源码里提出来的一个 Characteristics// 只包含一个恒等函数的Characteristicsstatic final SetCH_ID = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
static class GroupByCollectorimplements Collector >, Map >> { Function classifier; public GroupByCollector(Function classifier) { this.classifier = classifier; } @Override public Supplier
简化代码
static class GroupByCollector2implements Collector >, Map >> { Function classifier; public GroupByCollector2(Function classifier) { this.classifier = classifier; } @Override public Supplier >> supplier() { return HashMap::new; } @Override public BiConsumer >, T> accumulator() { return (map, e) -> { K key = classifier.apply(e); List value = Optional.ofNullable(map) .map(m -> m.get(key)).orElse(Lists.newArrayList()); value.add(e); map.put(key, value); }; } @Override public BinaryOperator >> combiner() { return (m1, m2) -> { m2.forEach((k, v) -> { List value = Optional.ofNullable(m1) .map(m -> m.get(k)).orElse(Lists.newArrayList()); value.addAll(v); m1.put(k, value); }); return m1; }; } @Override public Function >, Map >> finisher() { return Function.identity(); } @Override public Set characteristics() { return CH_ID; }}
使用自定义Collector
static class User { private Integer id; private String name; private Integer gender; private Integer age; User(Integer id, String name, Integer gender, Integer age) { this.id = id; this.name = name; this.gender = gender; this.age = age; } // getter,setter}Listusers = Lists.newArrayList( new User(1, "java", 1, 25), new User(2, "C", 1, 22), new User(3, "scala", 0, 23), new User(4, "C++", 0, 11), new User(5, "Spark", 1, 25), new User(6, "PHP", 0, 45), new User(7, "Python", 1, 89), new User(8, "JavaScript", 0, 110), new User(9, "C#", 1, 33));void printUserMap(Map > map) { map.forEach((k, v) -> { System.out.println(k); v.forEach(e-> System.out.println("\t"+e)); });}@Testpublic void test2() { Map > map = users.stream() .collect(Collectors.groupingBy(User::getGender)); printUserMap(map); map = users.stream(). collect(new GroupByCollector<>(User::getGender)); printUserMap(map); map = users.stream().collect(new GroupByCollector2<>(User::getGender)); printUserMap(map);}
- 输出效果
0 User{id=3, name='scala', gender=0, age=23} User{id=4, name='C++', gender=0, age=11} User{id=6, name='PHP', gender=0, age=45} User{id=8, name='JavaScript', gender=0, age=110}1 User{id=1, name='java', gender=1, age=25} User{id=2, name='C', gender=1, age=22} User{id=5, name='Spark', gender=1, age=25} User{id=7, name='Python', gender=1, age=89} User{id=9, name='C#', gender=1, age=33}