我有Stack<Object>
及以下代码:
while(!stack.isEmpty()){
Object object = stack.pop();
// do some operation on object
}
如何使用Java 8 Stream实现此迭代,以便循环直到堆栈为空,并且在每次迭代中都应该通过从顶部弹出一个元素来减少堆栈?
答案 0 :(得分:7)
在Java 9中,将有一个3-arg版本的Stream.iterate(如for
循环 - 初始值,lambda用于确定输入结束,lambda用于确定下一个输入)这样做,虽然会有点紧张:
if (!stack.isEmpty()) {
Stream.iterate(stack.pop(),
e -> !stack.isEmpty(),
e -> stack.pop())
...
}
答案 1 :(得分:1)
如果您不想等待the Java 9 solution,这是一个在Java 8下工作的流工厂。
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操作而修改的流源(如弹出Stream消耗的元素)可能会使源处于不可预测的状态。短路操作可能不会消耗所有元素,并且与并行流相结合,它们仍然可能消耗比终端操作所需的元素更多的元素。
执行终端流操作后,无法保证读者将处于读取下一个字符或行的特定位置。
在以这种方式消费元素后,您不应对Stack
内容做出任何假设。
答案 2 :(得分:-1)
不可能使用堆栈流,因为它首先是先进先出顺序,第二,因为它基于迭代器会抛出ConcurrentModificationException
。仍然可能,但当与简单的for循环相比时当然不推荐:
IntStream.range(0, s.size()).forEach(i -> stack.pop());