简体   繁体   English

在Java 8中使用嵌套的for循环

[英]Using nested for loops in Java 8

I have below code where I am using nested for loops and I have some condition that breaks the inner for loop, and this improves the performance of this code. 我在下面的代码中使用嵌套的for循环,并且有一些条件破坏了内部的for循环,这提高了此代码的性能。

public static int getMaxValue(List<Integer> list) {
    int result = -1;
    for(int i=0; i<list.size(); i++) {
        for(int j=i+1; j<list.size(); j++) {
            if(list.get(j) - list.get(i) <= 0) break;
            if(list.get(j) - list.get(i) > result) {
                result = list.get(j) - list.get(i);
            }
        }
    }
    return result;
}

Now how can I use Java 8 streams to do the same logic? 现在如何使用Java 8流执行相同的逻辑? I have come up with below code: 我想出了以下代码:

public static int getMaxValue(List<Integer> list) {
    int[] result = { -1 };
    IntStream.range(0, list.size()).forEach(i -> {
        IntStream.range(i + 1, list.size()).forEach(j -> {
            if(list.get(j) - list.get(i) <= 0) return;

            if(list.get(j) - list.get(i) > result[0]) {
                result[0] = list.get(j) - list.get(i);
            }
        });
    });
    return result[0];
}

Here I cannot use a break statement in java streams, so I have used return statement, but that still runs the inner loop, as it will not break it the performance is not improved. 在这里,我不能在java流中使用break语句,因此我使用过return语句,但是它仍在运行内部循环,因为它不会中断它,因此性能不会得到改善。

If I understand your code, you're trying to find the maximum pairwise difference between any two elements in the input list. 如果我理解您的代码,您正在尝试查找输入列表中任何两个元素之间的最大成对差异。 You can do that with IntSummaryStatistics : 您可以使用IntSummaryStatistics做到这IntSummaryStatistics

public static int getMaxValue(List<Integer> list) {
    IntSummaryStatistics stats = list.stream()
        .mapToInt(Integer::intValue)
        .summaryStatistics();
    return stats.getMax() - stats.getMin();
}

This is an O(n) operation, with O(1) auxiliary storage. 这是O(n)操作,带有O(1)辅助存储。 There is still no need for an O(n²) operation. 仍然不需要O(n²)操作。 Ultimately, breaking out of a loop early is an optimization, but not a very effective one -- finding an approach with a lower asymptotic cost will always be more effective than just breaking out of a loop early. 归根结底,尽早突破循环是一种优化,但不是一个很有效的优化-找到一种渐近成本较低的方法总是比尽早突破循环更为有效。

If your intention is to find the maximum value, you could just do: 如果您打算寻找最大值,则可以执行以下操作:

list.stream()
     .mapToInt(Integer::intValue)
     .max();

It will return an OptionalInt which will be empty of your list is empty. 它将返回一个OptionalInt ,该列表将为空。

Otherwise not sure what you want to achieve with your code... 否则,不确定要用代码实现什么...

UPDATE After clarification from the Op. 更新经操作说明澄清。

Create a small class called MinMax which stores min and max , like: 创建一个名为MinMax的小类,该类存储minmax ,例如:

public class MinMax {
  private final int min;
  private final int max;

  private MinMax(int min, int max) {
    this.min = min;
    this.max = max;
  }

  public int getDifference() {
    return this.max - this.min;
  }

  public MinMax accept(int element) {
    int newMin = element < min ? element : min;
    int newMax = element > max ? element : max;

    if (newMin != min || newMax != max) {
      return new MinMax(newMin, newMax);
    } else {
      return this;
    }
  }

  public static MinMax seed() {
    return new MinMax(Integer.MAX_VALUE, Integer.MIN_VALUE);
  }
}

This new class takes care of keeping track of both minimum and maximum. 这个新类负责跟踪最小值和最大值。 Now you could do something like: 现在您可以执行以下操作:

int result = list.stream() 
                 .reduce(MinMax.seed(), MinMax::accept())
                 .getDifference();

Java stream offers a special functionality for this use case which is findFirst, it will stop iteration over the collection and return immediately. Java流为此使用情况提供了一个特殊功能,即findFirst,它将停止对集合的迭代并立即返回。 Check this https://www.google.ae/amp/s/www.geeksforgeeks.org/stream-findfirst-java-examples/amp/ 检查此https://www.google.ae/amp/s/www.geeksforgeeks.org/stream-findfirst-java-examples/amp/

Moreover you can apply your test condition with filter, you'll use filter to check and findFirst to stop. 此外,您可以使用过滤器应用测试条件,使用过滤器进行检查,并使用findFirst停止。 This is in general to do what you asked for. 通常,这是您所要求的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM