[英]Common element in Java infinite streams
I have three infinite Java IntStream
objects. 我有三个无限的Java IntStream
对象。 I want to find the smallest element that is present in all three of them. 我想找到所有这三个元素中存在的最小元素。
IntStream a = IntStream.iterate(286, i->i+1).map(i -> (Integer)i*(i+1)/2);
IntStream b = IntStream.iterate(166, i->i+1).map(i -> (Integer)i*(3*i-1)/2);
IntStream c = IntStream.iterate(144, i->i+1).map(i -> i*(2*i-1));
I can always employ a brute force solution (without streams) which involves iterating in nested loops, but I was wondering if we can do it more efficiently with streams? 我总是可以采用蛮力解决方案(不使用流),该解决方案涉及在嵌套循环中进行迭代,但是我想知道我们是否可以使用流更有效地做到这一点?
You need to iterate all 3 in parallel, advancing the one with the lowest value, checking if all 3 are equal. 您需要并行地迭代所有3个对象,以最低的值前进一个对象,并检查所有3个对象是否相等。
You code will not find an answer for next value after 40755
, because the next value is 1_533_776_805
, which has intermediate value (before division by 2) higher than Integer.MAX_VALUE
( 2_147_483_647
). 您的代码将找不到40755
之后的下一个值的答案,因为下一个值是1_533_776_805
,该中间值(除以2之前)比Integer.MAX_VALUE
( 2_147_483_647
)高。
So, here is one way to use your streams, after changing them to long
and guarding against overflow. 因此,在将流更改为long
并防止溢出之后,这是使用流的一种方法。
LongStream a = LongStream.iterate(286, i->i+1).map(i -> Math.multiplyExact(i, i+1)/2);
LongStream b = LongStream.iterate(166, i->i+1).map(i -> Math.multiplyExact(i, 3*i-1)/2);
LongStream c = LongStream.iterate(144, i->i+1).map(i -> Math.multiplyExact(i, 2*i-1));
OfLong aIter = a.iterator();
OfLong bIter = b.iterator();
OfLong cIter = c.iterator();
long aVal = aIter.nextLong();
long bVal = bIter.nextLong();
long cVal = cIter.nextLong();
while (aVal != bVal || bVal != cVal) {
long min = Math.min(Math.min(aVal, bVal), cVal);
if (aVal == min)
aVal = aIter.nextLong();
if (bVal == min)
bVal = bIter.nextLong();
if (cVal == min)
cVal = cIter.nextLong();
}
System.out.println(aVal);
These functions are always increasing. 这些功能一直在增加。 So the code should stop when the magic equal triplet is found. 因此,当找到相等的三元组时,代码应停止。
The thing to code is: 要编码的是:
a) when a stream's current value is below any other, it can iterate next for itself. a)当流的当前值低于任何其他值时,它可以自己进行下一个迭代。
b) when it meets the same candidate value, it waits for the 3rd stream to take a decision. b)当满足相同的候选值时,它等待第三流做出决定。
c) when it has a higher value than the all others, it changes the candidate and waits for both others. c)当其价值高于所有其他价值时,它将更改候选人并等待其他两个人。
Reference juggling. 参考杂耍。
There may not be a solution too (at least in short time). 可能也没有解决方案(至少在短时间内)。
Notice that stream c can only produce even numbers (when seeded with even). 请注意,流c只能产生偶数(当使用偶数进行播种时)。 There might be some optimization there to skip a and b faster. 可能有一些优化可以更快地跳过a和b。
I don't think there is anything smart possible with stream API. 我认为流API不可能有任何明智的选择。 The main reason is that you can't really go over one stream until some condition is met - instead, you look at current 3 elements and pick the next element from one of the streams before comparing the elements again. 主要原因是,在满足某些条件之前,您无法真正遍历一个流-而是查看当前的3个元素,并从一个流中选择下一个元素,然后再次比较这些元素。
The most efficient (and might be also the cleanest) solution is to use iterators and keep calling next()
method on the right streams until the answer is found. 最有效(也是最干净的)解决方案是使用迭代器,并在正确的流上继续调用next()
方法,直到找到答案为止。
To start with, you can focus on two streams only and find their first common value: 首先,您可以仅关注两个流并找到它们的第一个共同价值:
while (elementA != elementB) {
if (elementA < elementB) {
elementA = iteratorA.next();
} else {
elementB = iteratorB.next();
}
}
Then you need to do make third stream catch up with these two: 然后,您需要使第三流赶上这两个:
while (elementC < elementA) {
elementC = iteratorC.next();
}
At this point there are two options: 此时有两种选择:
elementC == elementA
in which case you have the answer 任一个elementC == elementA
在这种情况下,您都有答案 elementC > elementA
in which case you can go to next value on all three streams and start over 或elementC > elementA
在这种情况下,您可以在所有三个流上转到下一个值并重新开始 One thing to remember is the max value of integer. 要记住的一件事是整数的最大值。 Because you have i^2
, this means that it will overflow for i
about 46k, so you need to change streams of ints to streams of longs (the answer is about 1.5 billion - and that's after division by 2 in these functions). 因为您有i^2
,这意味着它将在i
溢出约46k,因此您需要将int流更改为long流(答案约为15亿-并且在这些函数中被2除后)。
Since you are doing exercises for practice, I don't think it's right to give you the full working code, but let me know if you still struggle with it ;) 由于您正在练习练习,因此我认为向您提供完整的工作代码并不正确,但请告诉我您是否仍在努力;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.