如何使用 Java 8 Stream 实现 Stack Iteration
How to implement Stack Iteration using Java 8 Stream
我有一个 Stack<Object>
和以下代码:
while(!stack.isEmpty()){
Object object = stack.pop();
// do some operation on object
}
如何使用 Java 8 Stream 实现此迭代,以便它循环直到堆栈为空,并且在每次迭代中都应通过从顶部弹出一个元素来减少堆栈?
不可能使用堆栈流,因为首先它是先进先出的顺序,其次是因为它基于迭代器会抛出 ConcurrentModificationException
。仍然可能,但与简单的 for 循环相比当然不推荐:
IntStream.range(0, s.size()).forEach(i -> stack.pop());
在 Java 9 中,将有一个 Stream.iterate 的 3-arg 版本(类似于 for
循环——初始值,用于确定输入结束的 lambda, lambda 用于确定下一个输入)可以做到这一点,虽然它会有点紧张:
if (!stack.isEmpty()) {
Stream.iterate(stack.pop(),
e -> !stack.isEmpty(),
e -> stack.pop())
...
}
如果您不想等待 ,这里有一个在 Java8 下工作的流工厂。
public static <T> Stream<T> pop(Stack<T> stack) {
return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(
stack.size(), Spliterator.ORDERED|Spliterator.SIZED) {
public boolean tryAdvance(Consumer<? super T> action) {
if(stack.isEmpty()) return false;
action.accept(stack.pop());
return true;
}
}, false);
}
请注意,这会报告堆栈的初始大小,这是理所当然的,这意味着您不能在中间更改堆栈(无论如何在中间修改流源都是一个坏主意)。另一方面,这将使某些流操作比迭代变体更有效。
现在,适用于两种变体的一般警告。由于正在进行的 Stream 操作(如弹出 Stream 使用的元素)而修改的流源可能会使源处于不可预测的状态。短路操作可能不会消耗所有元素,并且结合并行流,它们仍然可能消耗比终端操作所需更多的元素。
After execution of the terminal stream operation there are no guarantees that the reader will be at a specific position from which to read the next character or line.
你不应该对以这种方式消耗元素后的 Stack
内容做出任何假设。
我有一个 Stack<Object>
和以下代码:
while(!stack.isEmpty()){
Object object = stack.pop();
// do some operation on object
}
如何使用 Java 8 Stream 实现此迭代,以便它循环直到堆栈为空,并且在每次迭代中都应通过从顶部弹出一个元素来减少堆栈?
不可能使用堆栈流,因为首先它是先进先出的顺序,其次是因为它基于迭代器会抛出 ConcurrentModificationException
。仍然可能,但与简单的 for 循环相比当然不推荐:
IntStream.range(0, s.size()).forEach(i -> stack.pop());
在 Java 9 中,将有一个 Stream.iterate 的 3-arg 版本(类似于 for
循环——初始值,用于确定输入结束的 lambda, lambda 用于确定下一个输入)可以做到这一点,虽然它会有点紧张:
if (!stack.isEmpty()) {
Stream.iterate(stack.pop(),
e -> !stack.isEmpty(),
e -> stack.pop())
...
}
如果您不想等待
public static <T> Stream<T> pop(Stack<T> stack) {
return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(
stack.size(), Spliterator.ORDERED|Spliterator.SIZED) {
public boolean tryAdvance(Consumer<? super T> action) {
if(stack.isEmpty()) return false;
action.accept(stack.pop());
return true;
}
}, false);
}
请注意,这会报告堆栈的初始大小,这是理所当然的,这意味着您不能在中间更改堆栈(无论如何在中间修改流源都是一个坏主意)。另一方面,这将使某些流操作比迭代变体更有效。
现在,适用于两种变体的一般警告。由于正在进行的 Stream 操作(如弹出 Stream 使用的元素)而修改的流源可能会使源处于不可预测的状态。短路操作可能不会消耗所有元素,并且结合并行流,它们仍然可能消耗比终端操作所需更多的元素。
After execution of the terminal stream operation there are no guarantees that the reader will be at a specific position from which to read the next character or line.
你不应该对以这种方式消耗元素后的 Stack
内容做出任何假设。