应用流的 `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。我尝试使用常量 0e -> 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 containermutable 是这里的关键字。

所以,制作一个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]);