处理流中的一个元素而不关闭它

Den*_*ret 7 java functional-programming java-8 java-stream

我正在寻找一种干净有效的方法,将消费者应用于非并行流的一个元素而不关闭流.

我的意思是我想要替换

AtomicBoolean firstOneDone = new AtomicBoolean();
lines.forEach(line -> {
    if (!firstOneDone.get()) {
        // handle first line
        firstOneDone.set(true);
    } else {
        // handle any other line
    }
})
Run Code Online (Sandbox Code Playgroud)

有类似的东西

lines.forFirst(header -> {
    // handle first line        
}).forEach(line -> {
    // handle any other line
})
Run Code Online (Sandbox Code Playgroud)

我不想对整个流进行两次传递(复制或重新创建流peek等),或者只是将布尔/测试移动到另一个位置,如函数包装器.

这是可能的还是流的基本模型与这种部分阅读不兼容?

Oli*_*ire 9

不,这是不可能的,因为您的流管道在每次"最终"操作时都会关闭.另一种方法是使用Stream's迭代器.你只有一个迭代器.我想这就是你真正想要的,因为你坚持只创建一个流.但是你必须跳过"功能"部分.

Stream<String> strings = ... ;
Iterator<String> stringsIt = strings.iterator();
if (stringsIt.hasNext()) {
  System.out.printf("header: %s%n", stringsIt.next());
  while (stringsIt.hasNext()) {
    System.out.printf("line: %s%n", stringsIt.next());
  }
}
Run Code Online (Sandbox Code Playgroud)

另一种选择,有ZouZou的评论:

Stream<String> strings = ... ;
Iterator<String> stringsIt = strings.iterator();
if (stringsIt.hasNext()) {
  System.out.printf("header: %s%n", stringsIt.next());
  stringsIt.forEachRemaining(line -> { System.out.printf("line: %s%n", line); });
}
Run Code Online (Sandbox Code Playgroud)

所有功能的最终答案实际上如下:

Stream<String> lines = ... ;
Spliterator<String> linesIt = lines.spliterator();
linesIt.tryAdvance(header -> { System.out.printf("header: %s%n", header); });
linesIt.forEachRemaining(line -> { System.out.printf("line: %s%n", line); });
Run Code Online (Sandbox Code Playgroud)

  • Stream确实有一个`iterator()`方法.while循环可以用`stringsIt.forEachRemaining(s - > System.out.printf("line:%s%n",s))替换;`btw :) (4认同)
  • 分裂器方法非常整洁! (2认同)