Java8 : Using an IntStream as a Supplier parameter for custom Collector

标签 java java-8 functional-programming java-stream collectors

对于流对象,是不是可以使用collect方法写一个自定义的Collector对象,收集到另一个流对象?我最近才了解流,并试图获得尽可能多的经验,但我遇到了这个问题。

我的代码是:

    // 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();
    }

此代码编译并且 collect 方法对流中的第一个 String 运行良好,但它第二次到达 IntStream.concat(s1, cs) 时出现以下异常:

java.lang.IllegalStateException: stream has already been operated upon or closed

我对此的解释是,一旦我的第一个 String 转换为 IntStream 并且 collect 方法移动到下一个 String,我的第一个 IntStream 就会关闭。那是对的吗?为什么会这样?

这是我为自己发明的练习,目的是尝试获得更多关于流和函数式编程的经验。我知道这可能不是编写此方法的最佳方式。我想知道为什么这行不通,而不是我可以采取的其他方法。

最佳答案

通过调用 concat,您不会改变 s1concat 返回 连接后的流。流首先是不可变的。

这意味着您开始时使用的 Stream.empty 从未改变,并且在 concat 方法中一次又一次地使用它。但是,您不能concat 中使用流两次。这算作“对流进行操作”。因此,当您第二次尝试执行此操作时,您会遇到记录在案的非法状态异常:

A stream should be operated on (invoking an intermediate or terminal stream operation) only once. This rules out, for example, "forked" streams, where the same source feeds two or more pipelines, or multiple traversals of the same stream. A stream implementation may throw IllegalStateException if it detects that the stream is being reused. However, since some stream operations may return their receiver rather than a new stream object, it may not be possible to detect reuse in all cases.

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

public static int uniqueLetters(Stream<String> stream){
    return (int)stream.flatMapToInt(String::chars).distinct().count();
}

flatMap 可能是您试图通过收集到流来做的事情。现在您知道这叫做 flatMap

关于Java8 : Using an IntStream as a Supplier parameter for custom Collector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50159258/

相关文章:

java - 在 Java 中的不同属性文件之间共享公共(public)属性

java - 使用java从css中提取十六进制颜色

functional-programming - 函数式编程类(class)结束时的 2 个问题

haskell - Monadic 杂质和 Haskell 纯度。它们是如何结合的?

java - Ajax 将 JSON 数组发送到 servlet

java - ResultSet 没有从 Oracle DB 中获取所有数据

java - 通过某个键将 <Long, List<String>> 映射到字符串 Lambda 列表

java - 使用 java 8 流生成一个 N 个字符长的虚拟字符串

java - 使用 ConcurrentHashSet 时的线程安全引用分配

scala - 在 Scala 中,如何组契约(Contract)一个 List 的元素序列?