我正在尝试使用 java9 的 takeWhile 过滤排序流,以从流的开头获取共享相同字段值的对象。我无法编写正确的谓词来这样做。这可以通过打破流的管道的两个步骤来完成。
Stream.of(objA, objB, objC, objD, objE, objF, objG)
.takeWhile(" get the value of objA´s field and take
as long as as other objects value for that field is the same as objA´s");
分两步,我可以做类似的事情
int x = Stream.of(objA, objB, objC, objD, objE, objF, objG).findFirst().get().getSomeValue();
Stream.of(objA, objB, objC, objD, objE, objF, objG).takeWhile(e -> e.getSomeValue() == x);
一个简化的例子可能是
Stream.of(5,5,5,5,13,14,5,5,2,5,5,6)
.takeWhile(get the first four '5'´s)
这可以在没有使用 optional.get 的中间步骤的情况下完成吗?
最佳答案
一个(有点笨拙的)解决方法是使用包含 null
或第一个值的可变持有者对象(因为引用必须是 effectively final )。我们将在本例中使用 AtomicReference
。
AtomicReference<MyClass> holder = new AtomicReference<>();
sortedStream.takeWhile(e -> holder.get() == null || holder.get().equals(e))
.map(e -> { holder.set(e); return e; })
.collect(Collectors.toList());
现在这仍然包含一个额外的步骤,但是由于
Stream
只能处理一次,因此 findFirst()
方法无论如何都不起作用。即使它已经被设置,这也会继续设置持有者对象,但这只是一个小烦恼而不是一个问题。正如 Holger 指出的那样,一个更好、更精简的版本将是
sortedStream.takeWhile(e -> holder.compareAndSet(null, e.getSomeValue()) || e.getSomeValue() == holder.get())
.collect(Collectors.toList());
其中第一个元素
compareAndSet
分配值,返回 true,随后的元素与持有者的值进行比较。如果您确实使用这种方法,我建议添加指向此问题/答案的注释,或者至少尝试以某种方式解释此代码实现的功能,因为对于阅读代码的人来说,这可能不是很明显。
关于java - 同一管道中已排序流的 Stream takeWhile,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58665470/