【问题标题】:How to get the index and max value of an array in one shot?如何一次性获取数组的索引和最大值?
【发布时间】:2015-06-09 11:35:03
【问题描述】:

给定一个整数元素列表,如何一次性获得最大值和它的索引。如果有多个元素具有相同的最大值,则返回其中任何一个的索引都可以。

例如:

// Initialize list of integer
List<Integer> intList = Arrays.asList(5, 8, 3, 2);
// To get max value
Optional<Integer> maxVal = intList.stream().reduce(Integer::max);
// But how could I also get its index without iterating the array again?

如果我只需要执行一次,我可以对数组进行排序并获取第一个或最后一个(基于排序顺序)。但是,我想看看我们如何在不排序的情况下做到这一点。

【问题讨论】:

    标签: java-8 java-stream


    【解决方案1】:

    通常,如果您需要索引,则必须通过索引进行流式传输。然后,任务就变得直截了当:

    List<Integer> intArr = Arrays.asList(5, 8, 3, 2);
    IntStream.range(0, intArr.size())
      .reduce((a,b)->intArr.get(a)<intArr.get(b)? b: a)
      .ifPresent(ix->System.out.println("Index "+ix+", value "+intArr.get(ix)));
    

    一个更优雅的解决方案,不幸的是结合了拳击开销

    IntStream.range(0, intArr.size())
      .boxed().max(Comparator.comparing(intArr::get))
      .ifPresent(ix->System.out.println("Index "+ix+", value "+intArr.get(ix)));
    

    【讨论】:

    • 盒装有什么意义?
    • @SriniK 我相信那是因为你不能拥有Comparator&lt;int&gt;。但同样,我可能错了,因为我对 Java 8 还是有点陌生​​。
    • @Chetan Kinger:你是对的,没有Comparator&lt;int&gt; 等等,IntStream 没有提供max(Comparator) 方法,但只有max() 在这里没有帮助(同样适用于min 或sorted,IntStream 仅支持自然顺序)。
    • @Holger 为什么不直接使用intArr.stream().max(comparator)呢?
    • @AlikElzin-kilaka:这是一个O(n) 操作。没有指定将处理哪些元素,因为归约函数需要是关联的,所以它可能会做((e1 op e2) op e3) op e4 或(e1 op e2) op (e3 op e4),但你看,在任何一种情况下,操作的数量都是相同的。 max 操作只是一个特殊的内置归约,具有完全相同的时间复杂度。
    【解决方案2】:

    如果您不介意使用第三方代码,我的 StreamEx 库为这项任务提供了一些快捷方式:

    List<Integer> intArr = Arrays.asList(5, 8, 3, 2);
    IntStreamEx.ofIndices(intArr)
               .maxBy(intArr::get)
               .ifPresent(ix->System.out.println("Index "+ix+", value "+intArr.get(ix)));
    

    在内部它接近于@Holger 提供的第一个解决方案(没有装箱)。

    【讨论】:

      【解决方案3】:

      我认为目前没有任何解决方案与手动迭代一样快:

      int maxValueIndex = 0;
      Integer maxValue = null;
      for (int i = 0, n = intList.size(); i < n; ++i) {
          Integer value = intList.get(i);
          if (value == null || maxValue != null && value <= maxValue)
              continue;
          maxValue = value;
          maxValueIndex = i;
      }
      

      【讨论】:

        【解决方案4】:

        在java8你可以execute streams in parallel

        Integer[] intArr= {1,2,6,2,234,3,54,6,4564,456};
        
        IntStream.range(0, intArr.length-1).parallel().
                        reduce((a,b)->intArr[a]<intArr[b]? b: a).
                        ifPresent(ix -> System.out.println("Index: " + ix + ", value: " + intArr[ix]));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-09-11
          • 2021-12-03
          • 2018-12-09
          • 1970-01-01
          • 2021-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多