java8-08-自定义Collector-groupBy

  • 声明
  • 简单实现
  • 简化代码
  • 使用自定义Collector
  • 博客源码

声明

这一系列文章旨在帮助大家理解 Collector 的执行流程,至于实现的是否高效、是否优雅、是否合理等暂且不论。


现在来实现一个和 java.util.stream.Collectors#groupingBy() 一样效果的 GroupByCollector

当然此处的实现肯定没有jdk那样灵活,效率就先不提了,至少贫道的这个实现不支持多级分组V_V。

若对 Collector 的各个流程有疑问请移驾此处:http://blog.csdn.net/hylexus/article/details/78941843

简单实现

// 这个是从jdk8源码里提出来的一个 Characteristics
// 只包含一个恒等函数的Characteristics
static final Set CH_ID
        = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
static class GroupByCollector implements Collector>, Map>> {

    Function classifier;

    public GroupByCollector(Function classifier) {
        this.classifier = classifier;
    }

    @Override
    public Supplier>> supplier() {
        return () -> new HashMap<>();
    }

    @Override
    public BiConsumer>, T> accumulator() {
        return (map, e) -> {
            K key = classifier.apply(e);
            List value = map.get(key);
            if (map.get(key) == null) {
                map.put(key, Lists.newArrayList());
            }

            map.get(key).add(e);
        };
    }

    @Override
    public BinaryOperator>> combiner() {
        return (map1, map2) -> {
            map2.forEach((k, v) -> {
                if (map1.get(k) == null) {
                    map1.put(k, v);
                } else {
                    map1.get(k).addAll(v);
                }
            });
            return map1;
        };
    }

    @Override
    public Function>, Map>> finisher() {
        return Function.identity();
    }

    @Override
    public Set characteristics() {
        return CH_ID;
    }
}

简化代码

static class GroupByCollector2 implements 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
}

List users = 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));
    });
}

@Test
public 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}

博客源码

https://github.com/hylexus/blog-src/blob/master/java-core/src/test/java/cn/hylexus/lambda/CollectorTest.java

你可能感兴趣的:(JavaSE)