- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在使用 takeWhile 创建片段来探索它的可能性。与 flatMap 配合使用时,行为不符合预期。请在下面找到代码片段。
String[][] strArray = {{"Sample1", "Sample2"}, {"Sample3", "Sample4", "Sample5"}};
Arrays.stream(strArray)
.flatMap(indStream -> Arrays.stream(indStream))
.takeWhile(ele -> !ele.equalsIgnoreCase("Sample4"))
.forEach(ele -> System.out.println(ele));
实际输出:
Sample1
Sample2
Sample3
Sample5
预期输出:
Sample1
Sample2
Sample3
期望的原因是 takeWhile 应该一直执行到内部条件变为真为止。我还在 flatmap 中添加了打印输出语句以进行调试。流仅返回两次,符合预期。
但是,如果链中没有平面图,这也可以正常工作。
String[] strArraySingle = {"Sample3", "Sample4", "Sample5"};
Arrays.stream(strArraySingle)
.takeWhile(ele -> !ele.equalsIgnoreCase("Sample4"))
.forEach(ele -> System.out.println(ele));
实际输出:
Sample3
此处实际输出与预期输出匹配。
免责声明:这些片段仅用于代码练习,不提供任何有效的用例。
更新:错误 JDK-8193856 : 修复将作为 JDK 10 的一部分提供。更改将更正 whileOps
接收器::接受
@Override
public void accept(T t) {
if (take = predicate.test(t)) {
downstream.accept(t);
}
}
改变的实现:
@Override
public void accept(T t) {
if (take && (take = predicate.test(t))) {
downstream.accept(t);
}
}
最佳答案
这是 JDK 9 中的一个错误 - 来自 issue #8193856 :
takeWhile
is incorrectly assuming that an upstream operation supports and honors cancellation, which unfortunately is not the case forflatMap
.
如果流是有序的,takeWhile
应该显示预期的行为。这在您的代码中并不完全如此,因为您使用 forEach
,它放弃了订单。如果你关心它,你在这个例子中做了,你应该使用 forEachOrdered
代替。有趣的是:这并没有改变任何事情。 🤔
所以也许一开始就没有对流进行排序? (在那种情况下 the behavior is ok 。)如果为从 strArray
创建的流创建临时变量,并通过执行表达式 ((StatefulOp) stream).isOrdered( );
在断点处,你会发现确实是有序的:
String[][] strArray = {{"Sample1", "Sample2"}, {"Sample3", "Sample4", "Sample5"}};
Stream<String> stream = Arrays.stream(strArray)
.flatMap(indStream -> Arrays.stream(indStream))
.takeWhile(ele -> !ele.equalsIgnoreCase("Sample4"));
// breakpoint here
System.out.println(stream);
这意味着这很可能是一个实现错误。
正如其他人所怀疑的那样,我现在也认为这个可能与 flatMap
的渴望有关。更准确地说,这两个问题可能具有相同的根本原因。
查看WhileOps
的源码,我们可以看到这些方法:
@Override
public void accept(T t) {
if (take = predicate.test(t)) {
downstream.accept(t);
}
}
@Override
public boolean cancellationRequested() {
return !take || downstream.cancellationRequested();
}
takeWhile
使用此代码来检查给定的流元素 t
是否满足 predicate
:
downstream
操作,在本例中为 System.out::println
。take
设置为 false,因此当下次询问是否应该取消管道时(即已完成),它返回 true
。 这涵盖了 takeWhile
操作。您需要知道的另一件事是 forEachOrdered
导致终端操作执行方法 ReferencePipeline::forEachWithCancel
:
@Override
final boolean forEachWithCancel(Spliterator<P_OUT> spliterator, Sink<P_OUT> sink) {
boolean cancelled;
do { } while (
!(cancelled = sink.cancellationRequested())
&& spliterator.tryAdvance(sink));
return cancelled;
}
所有这些都是:
看起来很有希望,对吧?
flatMap
在“好的情况下”(没有 flatMap
;您的第二个示例)forEachWithCancel
直接在 WhileOp
上作为 sink
,你可以看到这是怎么回事:
ReferencePipeline::forEachWithCancel
执行其循环:
WhileOps::accept
被赋予每个流元素WhileOps::cancellationRequested
在每个元素之后查询"Sample4"
谓词失败并且流被取消耶!
flatMap
在“坏情况”(使用 flatMap
;您的第一个示例)中,forEachWithCancel
对 flatMap
操作进行操作,但是,只需为 {"Sample3", "Sample4", "Sample5"}
在 ArraySpliterator
上调用 forEachRemaining
,它会这样做:
if ((a = array).length >= (hi = fence) &&
(i = index) >= 0 && i < (index = hi)) {
do { action.accept((T)a[i]); } while (++i < hi);
}
忽略所有 hi
和 fence
东西,仅在数组处理被拆分为并行流时使用,这是一个简单的 for
循环,它将每个元素传递给 takeWhile
操作,但从不检查它是否被取消。因此,它会在停止之前急切地遍历该“子流”中的所有元素,甚至可能是 through the rest of the stream .
关于java - takeWhile() 与平面图的工作方式不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47888814/
在我针对 SQL Server 2012 实例运行的以下 Linq 查询中,我尝试读取最新记录,直到之前建立的 MasterId标记(这是一个 Guid )。 var cdc = crm.CdcCon
我正在运行以下代码: val it = List(1,1,1,2,2,3,3).iterator.buffered val compare = it.head it.takeWhile(_ ==
我有一些从 Haskell 调用的用 C 语言编写的函数。这些函数返回 IO (CInt) .有时我想运行所有函数,而不管它们返回什么,这很容易。为了示例代码,这是当前正在发生的事情的一般概念: Pr
我有一个 RxJS5 管道看起来像这样 Rx.Observable.from([2, 3, 4, 5, 6]) .takeWhile((v) => { v !== 4 }) 我想保留订阅直到看到
我是 Haskell 的新手,正在尝试执行以下操作: takeWhile (length < 3) [[1],[1,2],[1..3],[1..4]] .但这给出了一个错误,我认为这是因为 takeW
我有类似以下内容: [bla z|n 1) , let z = 10*n , _ ) = ap instance Monad F w
我想要一些能够有效地执行与 TakeWhile 相同但返回两个序列的东西: TakeWhile 的结果 1. 删除了输入序列的其余部分 我知道我可以做这样的事情: var a = input.Take
如何编写一个 takeWhile 来保留第一个不符合条件的元素? 示例(显然我的示例比这更棘手): 而不是 takeWhile (\× - > x! = 3) [1..10]返回 [1,2]我需要[1
我想要一些能够有效地执行与 TakeWhile 相同但返回两个序列的东西: TakeWhile 的结果 1. 删除了输入序列的其余部分 我知道我可以做这样的事情: var a = input.Take
似乎没有 e.TakeWhile(predicate, atLeastNElements) 重载。有没有一种方便的方式来表达TakeWhile,但是,如果有>= N个元素可用的话,至少要取N个元素。?
如何使用折叠在 Haskell 中实现 takeWhile 函数? takeWhile :: (a -> Bool) -> [a] -> [a] 我尝试了一种类似于实现这样的过滤器的策略 filter
我想知道是否有办法添加根据方法 takeWhile() 的条件测试的流的最后一个元素。我相信我想实现类似于 RxJava 的 takeUntil() 方法的东西。 我猜没有直接的方法可以做到这一点(如
有 public static IEnumerable FibonacciNumbers() { long current = 0; long next = 1; while (true) {
我想在 LINQ to Objects 上使用 LINQ TakeWhile 函数。但是,我还需要知道“破坏”函数的第一个元素,即条件不成立的第一个元素。 是否有一个函数可以获取所有不匹配的对象以及第
takeWhile() 与 Java 9 中的 filter() 有何不同。它有什么额外的实用程序? Stream.of(1,2,3,4,5,6,7,8,9,10).filter(i -> i i
我正在使用 takeWhile 创建片段来探索它的可能性。与 flatMap 配合使用时,行为不符合预期。请在下面找到代码片段。 String[][] strArray = {{"Sample1",
val i = (1 to 8).toIterator val oneToThree = i.takeWhile(_ val i = (1 to 8).iterator i: Iterator[In
我看到它们(where 和 takeWhile)具有相同的功能..否则我可能会在这里漏掉一些东西! 最佳答案 documentation for Iterable.where说: Returns a
isqrt :: Integer -> Integer isqrt = floor . sqrt . fromIntegral primes :: [Integer] primes = sieve [
Javadoc指出 This is a short-circuiting stateful intermediate operation. 有状态的定义来自 Javadoc : Stateful op
我是一名优秀的程序员,十分优秀!