应用流的 `collec()` 进行计数。锻炼
Applying the `collec()` of stream for counting. Exercise
我正在尝试创建自定义收集器以计算列表的有效元素。我已经使用其中一个已经提供的收集器完成了它:
arr.stream()
.filter(e -> e.matches("[:;][~-]?[)D]"))
.map(e -> 1)
.reduce(0, Integer::sum);
但作为对自己的挑战,我想创建自己的自定义收集器以便更好地理解它。这就是我卡住的地方。
这可能是微不足道的事情,但我正在学习这个并且无法计算供应商,累加器和组合器。我想我还是对他们有些不了解。例如,我有一个类似的流:
arr1.stream()
.filter(e -> e.matches("[:;][~-]?[)D]"))
.map(e -> 1)
.collect(temporary array, adding to array, reduce);
AFAIK supplier 是一个没有参数的函数,return 有点意思。我研究了标准示例,它通常是新集合的方法参考,例如ArrayList::new
。我尝试使用常量 0
、e -> 0
因为我想 return 一个标量。我认为这是错误的,因为它使流 returning 为 0。如果对临时集合使用方法引用,Java 会抱怨供应商和 returning 对象的类型不匹配。如果最终结果是一个数字,我也对使用累加器感到困惑,因为组合器会将所有元素减少为一个数字,例如(a,b) -> a + b`.
我完全被难住了。
您的部分问题可能是您显然无法为 Integer 类型创建累加器,因为它是不可变的。
你从这个开始:
System.out.println(IntStream.of(1,2,3).reduce(0, Integer::sum));
您可以扩展到:
System.out.println(IntStream.of(1,2,3).boxed()
.collect(Collectors.reducing(0, (i1,i2)->i1+i2)));
甚至这个,它有一个中间映射功能
System.out.println(IntStream.of(1,2,3).boxed()
.collect(Collectors.reducing(0, i->i*2, (i1,i2)->i1+i2)));
您可以使用自己的收集器做到这一点
Collector<Integer, Integer, Integer> myctry = Collector.of(
()->0,
(i1,i2)->{
// what to do here?
},
(i1,i2)->{
return i1+i2;
}
);
累加器是 A function that folds a value into a mutable result container
,mutable 是这里的关键字。
所以,制作一个mutable integer
public class MutableInteger {
private int value;
public MutableInteger(int value) {
this.value = value;
}
public void set(int value) {
this.value = value;
}
public int intValue() {
return value;
}
}
现在:
Collector<MutableInteger, MutableInteger, MutableInteger> myc = Collector.of(
()->new MutableInteger(0),
(i1,i2)->{
i1.set(i1.intValue()+i2.intValue());
},
(i1,i2)->{
i1.set(i1.intValue()+i2.intValue());
return i1;
}
);
然后:
System.out.println(IntStream.of(1,2,3)
.mapToObj(MutableInteger::new)
.collect(myc).intValue());
编辑:终结者只是对最终结果做任何事情。如果您没有故意设置它,那么它默认设置为 IDENTITY_FINISH
,即 Function.identity()
,表示 return 最终结果原样。
编辑:如果你真的很绝望:
Collector<int[], int[], int[]> mycai = Collector.of(
()->new int[1],
(i1,i2)->i1[0] += i2[0],
(i1,i2)->{i1[0] += i2[0]; return i1;}
);
System.out.println(IntStream.of(1,2,3)
.mapToObj(v->{
int[] i = new int[1];
i[0] = v;
return i;
})
.collect(mycai)[0]);
我正在尝试创建自定义收集器以计算列表的有效元素。我已经使用其中一个已经提供的收集器完成了它:
arr.stream()
.filter(e -> e.matches("[:;][~-]?[)D]"))
.map(e -> 1)
.reduce(0, Integer::sum);
但作为对自己的挑战,我想创建自己的自定义收集器以便更好地理解它。这就是我卡住的地方。
这可能是微不足道的事情,但我正在学习这个并且无法计算供应商,累加器和组合器。我想我还是对他们有些不了解。例如,我有一个类似的流:
arr1.stream()
.filter(e -> e.matches("[:;][~-]?[)D]"))
.map(e -> 1)
.collect(temporary array, adding to array, reduce);
AFAIK supplier 是一个没有参数的函数,return 有点意思。我研究了标准示例,它通常是新集合的方法参考,例如ArrayList::new
。我尝试使用常量 0
、e -> 0
因为我想 return 一个标量。我认为这是错误的,因为它使流 returning 为 0。如果对临时集合使用方法引用,Java 会抱怨供应商和 returning 对象的类型不匹配。如果最终结果是一个数字,我也对使用累加器感到困惑,因为组合器会将所有元素减少为一个数字,例如(a,b) -> a + b`.
我完全被难住了。
您的部分问题可能是您显然无法为 Integer 类型创建累加器,因为它是不可变的。
你从这个开始:
System.out.println(IntStream.of(1,2,3).reduce(0, Integer::sum));
您可以扩展到:
System.out.println(IntStream.of(1,2,3).boxed()
.collect(Collectors.reducing(0, (i1,i2)->i1+i2)));
甚至这个,它有一个中间映射功能
System.out.println(IntStream.of(1,2,3).boxed()
.collect(Collectors.reducing(0, i->i*2, (i1,i2)->i1+i2)));
您可以使用自己的收集器做到这一点
Collector<Integer, Integer, Integer> myctry = Collector.of(
()->0,
(i1,i2)->{
// what to do here?
},
(i1,i2)->{
return i1+i2;
}
);
累加器是 A function that folds a value into a mutable result container
,mutable 是这里的关键字。
所以,制作一个mutable integer
public class MutableInteger {
private int value;
public MutableInteger(int value) {
this.value = value;
}
public void set(int value) {
this.value = value;
}
public int intValue() {
return value;
}
}
现在:
Collector<MutableInteger, MutableInteger, MutableInteger> myc = Collector.of(
()->new MutableInteger(0),
(i1,i2)->{
i1.set(i1.intValue()+i2.intValue());
},
(i1,i2)->{
i1.set(i1.intValue()+i2.intValue());
return i1;
}
);
然后:
System.out.println(IntStream.of(1,2,3)
.mapToObj(MutableInteger::new)
.collect(myc).intValue());
编辑:终结者只是对最终结果做任何事情。如果您没有故意设置它,那么它默认设置为 IDENTITY_FINISH
,即 Function.identity()
,表示 return 最终结果原样。
编辑:如果你真的很绝望:
Collector<int[], int[], int[]> mycai = Collector.of(
()->new int[1],
(i1,i2)->i1[0] += i2[0],
(i1,i2)->{i1[0] += i2[0]; return i1;}
);
System.out.println(IntStream.of(1,2,3)
.mapToObj(v->{
int[] i = new int[1];
i[0] = v;
return i;
})
.collect(mycai)[0]);