自定义Java8收集器
我想检查如何实现自定义收集器 喂,我需要做点什么 (1) 字母频率图等词的分析 (2) 能够组合两个结果以获得单个结果自定义Java8收集器,java,lambda,java-8,collectors,Java,Lambda,Java 8,Collectors,我想检查如何实现自定义收集器 喂,我需要做点什么 (1) 字母频率图等词的分析 (2) 能够组合两个结果以获得单个结果 class CharHistogram implements Collector<String, Map<Character, Integer>, Map<Character, Integer>> { public static CharHistogram toCharHistogram(){ return ne
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));
}
}
我看不到合路器和修整器被调用,我相信这些需要正确设计,以实现我所寻找的
我错过了什么
编辑:
支持流和组合器的可能方法。但下面的代码不起作用
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;
}
类实现函数{
私有整数总字符读取;
私有地图直方图;
public int getTotalCharactersRead(){
返回totalCharactersRead;
}
公共地图getHistogram(){
返回直方图;
}
公共空间设置直方图(地图直方图){
这个直方图=直方图;
}
public void setTotalCharactersRead(整型totalCharactersRead){
this.totalCharactersRead=totalCharactersRead;
}
公共地图合并(地图地图2){
Map map1=此直方图;
map2.forEach((k,v)->map1.merge(k,v,(v1,v2)->v1+v2));
返回map2;
}
@凌驾
公共映射应用(字符串val){
char[]characters=val.toCharArray();
totalCharactersRead+=characters.length;
for(字符:个字符){
整数计数=1;
if(直方图包含字符){
计数=直方图。获取(字符);
计数++;
}
直方图。放置(字符、计数);
}
返回直方图;
}
}
公共静态收集器SummaryCharstream(
CharStreamHistogram){//TODO:这对吗?
收集器charstatstate=新收集器(){
@凌驾
公共供应商(){
返回CharStreamHistogram::新建;
}
@凌驾
公共双消费者累加器(){
//托多:在这里做什么?
返回null;
}
@凌驾
公共二进制运算符组合器(){
二进制运算符二进制运算符=(l,r)->{
l、 联合收割机(r);//托多:像这样的?
};
返回二进制运算符;
}
@凌驾
公共函数完成器(){
//托多:在这里做什么?
返回null;
}
@凌驾
公共集特征(){
返回集合.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED));
}
};
返回charstatstate;
}
您已经声明了特征。IDENTITY\u FINISH
-这明确表示不会调用finisher
,并且只有在并行流的情况下才会调用组合器 您的收集器不应具有任何状态。累加器对象应同时包含totalCharactersRead
和映射。@LouisWasserman谢谢。所以现在我将移除它。但我稍后会谈到这一点。我没有真正理解finisher()的作用。上述代码对于用例是否正确。是,收集器中的状态除外。对于这个用例,合并器和finisher都不是必需的。但是我需要能够合并两个结果。“我该怎么做呢?”约翰,你只有在平行流运行时才需要这种能力,除了我不太理解你的问题here@John当您想学习如何编写自定义收集器时,您仍然应该坚持最佳实践,学习这些。首先,没有理由自己实现收集器。您只需调用(…)的收集器
,传递三个或四个函数和可选特征。当您省略finisher时,IDENTITY\u FINISH
将自动添加。此外,您还可以在combiner函数中显示您知道Map.merge
,那么为什么不在累加器中也使用它呢?而且,不要将整个字符串复制到char[]
数组中,只用于for
循环。使用string.chars().forEach(…)
[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}
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;
}