[英]Custom Java 8 Collector
I would like to check how to implement a custom Collector. 我想检查一下如何实现自定义收集器。
Say, I have a need to do some 说,我需要做一些
(1) analysis on words like alphabet-frequency map and (2) ability to combine 2 results to get a single result. (1)对字母 - 频率图等词的分析和(2)将2个结果组合成单个结果的能力。
class CharHistogram implements Collector<String, Map<Character, Integer>, Map<Character, Integer>> {
public static CharHistogram toCharHistogram(){
return new CharHistogram();
}
@Override
public Supplier<Map<Character, Integer>> supplier() {
SysOut.print("supplier invoked");
return HashMap::new;
}
@Override
public BiConsumer<Map<Character, Integer>, String> accumulator() {
SysOut.print("accumulator invoked");
return (map, val) -> {
SysOut.print(val +" processed");
char[] characters = val.toCharArray();
for (char character : characters) {
int count = 1;
if (map.containsKey(character)) {
count = map.get(character);
count++;
}
map.put(character, count);
}
};
}
@Override
public BinaryOperator<Map<Character, Integer>> combiner() {
SysOut.print("combiner invoked");
return (map1, map2) -> {
SysOut.print(map1+" merged to "+map2);
map2.forEach((k, v) -> map1.merge(k, v, (v1, v2) -> v1 + v2));
return map1;
};
}
@Override
public Function<Map<Character, Integer>, Map<Character, Integer>> finisher() {
SysOut.print("finisher invoked");
return Function.identity();
}
@Override
public Set<java.util.stream.Collector.Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH, Characteristics.UNORDERED));
}
}
Client code: 客户代码:
CharHistogram charStatsState = CharHistogram.toCharHistogram();
Map<Character, Integer> charCountMap = Arrays.asList("apple","orange","orange").stream().collect(charStatsState);
SysOut.print(charCountMap);
charCountMap = Arrays.asList("pears","pears","orange").stream().collect(charStatsState);
SysOut.print(charCountMap);
Output: 输出:
[main]: supplier invoked
[main]: accumulator invoked
[main]: combiner invoked
[main]: apple processed
[main]: orange processed
[main]: orange processed
[main]: {p=2, a=3, r=2, e=3, g=2, l=1, n=2, o=2}
[main]: supplier invoked
[main]: accumulator invoked
[main]: combiner invoked
[main]: pears processed
[main]: pears processed
[main]: orange processed
[main]: {p=2, a=3, r=3, s=2, e=3, g=1, n=1, o=1}
I don't see the combiner nor the finisher getting called and I believe these needs to be designed correctly to achieve what I'm looking for. 我没有看到组合器和整理器被调用,我相信这些需要正确设计才能实现我正在寻找的东西。
What am I missing? 我错过了什么?
EDIT: 编辑:
A possible approach to support streams and combiner. 支持流和组合器的可能方法。 The below code doesn't work though.
以下代码不起作用。
class CharStreamHistogram implements Function<String, Map<Character, Integer>>{
private int totalCharactersRead;
private Map<Character, Integer> histogram;
public int getTotalCharactersRead() {
return totalCharactersRead;
}
public Map<Character, Integer> getHistogram() {
return histogram;
}
public void setHistogram(Map<Character, Integer> histogram) {
this.histogram = histogram;
}
public void setTotalCharactersRead(int totalCharactersRead) {
this.totalCharactersRead = totalCharactersRead;
}
public Map<Character, Integer> combine(Map<Character, Integer> map2) {
Map<Character, Integer> map1 = this.histogram;
map2.forEach((k, v) -> map1.merge(k, v, (v1, v2) -> v1 + v2));
return map2;
}
@Override
public Map<Character, Integer> apply(String val) {
char[] characters = val.toCharArray();
totalCharactersRead += characters.length;
for (char character : characters) {
int count = 1;
if (histogram.containsKey(character)) {
count = histogram.get(character);
count++;
}
histogram.put(character, count);
}
return histogram;
}
}
public static <T> Collector<T, ?, CharStreamHistogram> summarizeCharStream(
CharStreamHistogram histogram) { //TODO: is this correct?
Collector charStatsState = new Collector<String, CharStreamHistogram, CharStreamHistogram>() {
@Override
public Supplier<CharStreamHistogram> supplier() {
return CharStreamHistogram::new;
}
@Override
public BiConsumer<CharStreamHistogram, String> accumulator() {
//TODO: What to do here?
return null;
}
@Override
public BinaryOperator<CharStreamHistogram> combiner() {
BinaryOperator binaryOperator = (l, r) -> {
l.combine(r); //TODO: Something like this?
};
return binaryOperator;
}
@Override
public Function<CharStreamHistogram, CharStreamHistogram> finisher() {
//TODO: What to do here?
return null;
}
@Override
public Set<java.util.stream.Collector.Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED));
}
};
return charStatsState;
}
那么你已经宣布Characteristics.IDENTITY_FINISH
-其中明确表示finisher
不会被调用,而combiner
仅在并行流的情况下被调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.