在 Java 8 中使用嵌套的 for 循环,找出给定的差异 [重复]
Posted
技术标签:
【中文标题】在 Java 8 中使用嵌套的 for 循环,找出给定的差异 [重复]【英文标题】:Using nested for loops in Java 8, to find out given difference [duplicate] 【发布时间】:2019-10-30 08:57:57 【问题描述】:我在下面的代码中使用了嵌套的 for 循环,并且我有一些条件破坏了内部 for 循环,这提高了该代码的性能。
假设提供的列表已经排序。现在我想找到差值等于某个值的元素的数量,比如k
。
public static int getCount(List<Integer> list, int k)
int result = 0;
for (int i = 0; i < list.size(); i++)
for (int j = i + 1; j < list.size(); j++)
if (list.get(j) - list.get(i) > k)
break;
if (list.get(j) - list.get(i) == k)
result++;
return result;
现在使用 Java 8 流的相同逻辑,这里跳过内循环我使用了 return
语句,但由于内循环没有被破坏,性能没有提高。
public static int getCount(List<Integer> list, int k)
int[] result = 0 ;
IntStream.range(0, list.size()).forEach(i ->
IntStream.range(i + 1, list.size()).forEach(j ->
if (list.get(j) - list.get(i) >= k)
return;
if (list.get(j) - list.get(i) == k)
result[0]++;
);
);
return result[0];
【问题讨论】:
@Alexei Kaigorodov,@Andy Turner,marked as duplicate
没有解释如何使用嵌套的 for 循环执行此操作。我的逻辑也是关于计算此类事件,链接没有解释。
副本清楚地表明,没有简单或惯用的方法可以突破 forEach
迭代。在 Java 9 中,您可以使用 takeWhile
。但即使这样也是解决问题的低效方法:它仍然是二次的,而您可以线性地解决(但不能使用流)。
与您之前的问题一样,您担心的是提前终止循环的微小改进,而不是寻找具有较低渐近成本的方法。如果列表已排序,则可以使用二分查找代替内部循环。或者,您在一个循环中为元素 e 及其 e+k 位置在列表中维护两个索引。
@Holger, Or you maintain two indices into the list for an element e and its e+k position in a single loop.
你能解释一下这是什么意思吗?我知道e
是列表中的一个元素,所以看看e+k
是否也出现在列表中。像这样,我必须为每个元素重复。看来我的想法和你的观点不同。
以index1
开头,e
的索引在0
。查找index2
,e+k
的索引,例如通过Collections.binarySearch
。现在进入循环:将index1
加一。由于列表已排序,新的e
大于旧的,因此e + k
的索引也必须大于旧的。提升index2
直到找到e+k
或达到大于e+k
的元素。重复直到index2
到达列表的末尾。然后,您无需再提出index1
,因为相应的e+k
不会出现在列表中。所以你完成了。 k
越大,需要检查的元素就越少……
【参考方案1】:
将您的内部IntStream.forEach()
替换为以下内容,看看它是否按预期工作:
IntStream.range(i + 1, list.size())
.filter(j -> list.get(j) - list.get(i) == k)
.forEach(j -> result[0]++);
【讨论】:
同样的问题,这里我们也没有打破内部循环,所以我遇到了性能问题。以上是关于在 Java 8 中使用嵌套的 for 循环,找出给定的差异 [重复]的主要内容,如果未能解决你的问题,请参考以下文章