[TOC]
聲明
這一系列文章旨在幫助大家理解 Collector
的執(zhí)行流程,至于實現(xiàn)的是否高效辟犀、是否優(yōu)雅俏竞、是否合理等暫且不論。
現(xiàn)在來實現(xiàn)一個和 java.util.stream.Collectors#groupingBy()
一樣效果的 GroupByCollector
。
當(dāng)然此處的實現(xiàn)肯定沒有jdk那樣靈活魂毁,效率就先不提了玻佩,至少貧道的這個實現(xiàn)不支持多級分組V_V。
若對 Collector
的各個流程有疑問請移駕此處:http://blog.csdn.net/hylexus/article/details/78941843
簡單實現(xiàn)
// 這個是從jdk8源碼里提出來的一個 Characteristics
// 只包含一個恒等函數(shù)的Characteristics
static final Set<Collector.Characteristics> CH_ID
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
static class GroupByCollector<T, K> implements Collector<T, Map<K, List<T>>, Map<K, List<T>>> {
Function<T, K> classifier;
public GroupByCollector(Function<T, K> classifier) {
this.classifier = classifier;
}
@Override
public Supplier<Map<K, List<T>>> supplier() {
return () -> new HashMap<>();
}
@Override
public BiConsumer<Map<K, List<T>>, T> accumulator() {
return (map, e) -> {
K key = classifier.apply(e);
List<T> value = map.get(key);
if (map.get(key) == null) {
map.put(key, Lists.newArrayList());
}
map.get(key).add(e);
};
}
@Override
public BinaryOperator<Map<K, List<T>>> 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<K, List<T>>, Map<K, List<T>>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return CH_ID;
}
}
簡化代碼
static class GroupByCollector2<T, K> implements Collector<T, Map<K, List<T>>, Map<K, List<T>>> {
Function<T, K> classifier;
public GroupByCollector2(Function<T, K> classifier) {
this.classifier = classifier;
}
@Override
public Supplier<Map<K, List<T>>> supplier() {
return HashMap::new;
}
@Override
public BiConsumer<Map<K, List<T>>, T> accumulator() {
return (map, e) -> {
K key = classifier.apply(e);
List<T> value = Optional.ofNullable(map)
.map(m -> m.get(key)).orElse(Lists.newArrayList());
value.add(e);
map.put(key, value);
};
}
@Override
public BinaryOperator<Map<K, List<T>>> combiner() {
return (m1, m2) -> {
m2.forEach((k, v) -> {
List<T> 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<K, List<T>>, Map<K, List<T>>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> 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<User> 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<Integer, List<User>> map) {
map.forEach((k, v) -> {
System.out.println(k);
v.forEach(e-> System.out.println("\t"+e));
});
}
@Test
public void test2() {
Map<Integer, List<User>> 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}