How to get the index and max value of an array in one shot?

17.8k views Asked by At

Given a list of integer elements, how to get the max value and it's index in one shot. If there is more than one element with same max value, returning index of any one of them is fine.

For example:

// 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?

If I have to do it only once, I could just sort the array and get the first or last one (based on sort order). However, I would like to see how we can do it without sorting.

4

There are 4 answers

7
Holger On BEST ANSWER

Generally, if you need an index, you’ll have to stream over the indices. Then, the task becomes straight-forward:

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)));

a more elegant solution, which unfortunately incorporates boxing overhead is

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

If you don't mind using third-party code, my StreamEx library provides some shortcuts for this task:

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)));

Internally it's close to the first solution provided by @Holger (no boxing).

0
frhack On

In java8 you can 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]));
0
rustyx On

I don't think there is currently any solution that's equally as fast as iterating manually:

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