Java8:使用IntStream作为自定义收集器的供应商参数

Java8:使用IntStream作为自定义收集器的供应商参数,java,java-8,functional-programming,java-stream,collectors,Java,Java 8,Functional Programming,Java Stream,Collectors,对于流对象,是否不能使用collect方法写入将收集到另一个流对象的自定义收集器对象?我最近刚刚学习了有关流的知识,并试图获得尽可能多的使用流的经验,我遇到了这个问题 我的代码是: // method to return how many unique letters are used in // the Strings in the given stream public int uniqueLetters(Stream<String> stream){

对于流对象,是否不能使用collect方法写入将收集到另一个流对象的自定义收集器对象?我最近刚刚学习了有关流的知识,并试图获得尽可能多的使用流的经验,我遇到了这个问题

我的代码是:

    // method to return how many unique letters are used in
    // the Strings in the given stream
    public int uniqueLetters(Stream<String> stream){
        // transfer Strings to an uppercase char stream
        IntStream allLets = stream.collect(IntStream::empty, 
                          (s1, s2) -> { String toAdd = s2.toUpperCase();
                                        IntStream cs = toAdd.chars();
                                        IntStream.concat(s1, cs); //exception thrown on this line
                                       }, IntStream::concat); 
        // use distinct on char stream and count
        return (int) allLets.distinct().count();
    }
//返回在中使用的唯一字母数的方法
//给定流中的字符串
公共整数唯一字母(流){
//将字符串传输到大写字符流
IntStream alllet=stream.collect(IntStream::empty,
(s1,s2)->{String toAdd=s2.toUpperCase();
IntStream cs=toAdd.chars();
IntStream.concat(s1,cs);//此行引发异常
},IntStream::concat);
//在字符流和计数上使用distinct
返回(int)allLets.distinct().count();
}
这段代码经过编译,collect方法对于流中的第一个字符串运行良好,但第二次到达IntStream.concat(s1,cs)时,我得到以下异常:

java.lang.IllegalStateException:流已被操作或关闭

我对此的解释是,一旦我的第一个字符串转换为IntStream,并且collect方法移动到下一个字符串,我的第一个IntStream就会关闭。对吗?为什么会发生这种情况


这是我为自己发明的一个练习,旨在获得更多关于流和函数编程的经验。我知道这可能不是编写此方法的最佳方式。我感兴趣的是知道为什么这不起作用,而不是我可以采取的其他方法。

通过调用
concat
,您没有变异
s1
concat
返回连接的流。首先,流是不可变的

这意味着您开始使用的
Stream.empty
从未更改,并且它在
concat
方法中反复使用。但是,不能在
concat
中使用流两次。这被视为“在流上操作”。因此,当您第二次尝试这样做时,您得到了一个非法状态异常,如文档所示:

应该对流进行操作(调用中间或终端) 流操作)仅一次。例如,这排除了“分叉”的可能性 流,其中同一源为两个或多个管道供电,或 同一流的多次遍历。可以使用流实现 如果检测到流正在运行,则抛出IllegalStateException 重复使用。但是,由于某些流操作可能返回其 接收器而不是新的流对象,可能无法 在所有情况下检测重用

要解决查找唯一字符的问题,不需要收集到流。只要这样做:

public static int uniqueLetters(Stream<String> stream){
    return (int)stream.flatMapToInt(String::chars).distinct().count();
}
公共静态int唯一字母(流){
return(int)stream.flatMapToInt(String::chars.distinct().count();
}
flatMap
可能就是您试图通过收集流来完成的。现在您知道了这叫做
flatMap