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

时间:2019-06-16 14:08:10

标签: java java-8

我在下面的代码中使用嵌套的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;
}

现在如何使用Java 8流执行相同的逻辑?我想出了以下代码:

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];
}

这里我不能在Java流中使用break语句,所以我使用了return语句,但是它仍然运行内部循环,因为它不会中断它,性能也不会得到改善。 / p>

3 个答案:

答案 0 :(得分:10)

如果我理解您的代码,您正在尝试查找输入列表中任意两个元素之间的最大成对差异。您可以使用IntSummaryStatistics

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

这是O(n)操作,带有O(1)辅助存储。仍然不需要O(n²)操作。归根结底,尽早突破循环是一种优化,但不是一种非常有效的优化方式-找到一种渐近成本较低的方法总是比早日摆脱循环更有效。 / p>

答案 1 :(得分:0)

如果您想找到最大值,则可以这样做:

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

它将返回一个OptionalInt,该列表将为空。

否则,不确定要使用代码实现什么...

更新。根据操作说明进行澄清。

创建一个名为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);
  }
}

这个新类负责跟踪最小和最大值。 现在您可以执行以下操作:

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

答案 2 :(得分:0)

Java流为此用例提供了一个特殊功能,即findFirst,它将停止对集合的迭代并立即返回。检查一下 https://www.google.ae/amp/s/www.geeksforgeeks.org/stream-findfirst-java-examples/amp/

此外,您可以将测试条件与过滤条件一起应用,然后使用过滤条件进行检查,并找到“首先停止”功能。通常,这是您所要求的。