Home > Net >  How to get the index of Arrays.stream(array).min()?
How to get the index of Arrays.stream(array).min()?

Time:11-16

I want to get the index of min, I tried ways like getIndexOf etc. but none of them worked. How can I do this?

import java.util.Arrays;
class getIndexOfMin {
    public static void main(String[] args) {

        double arr[] = {263.5, 393.75, 5.0, 289.75};

        double min = Arrays.stream(arr).min().getAsDouble();
        
        System.out.println(min);
    }
}

CodePudding user response:

You can make a stream of the indices of the array instead, from 0 to arr.length (exclusive):

Optional<Integer> minIndex = IntStream.range(0, arr.length).boxed()
    .min(Comparator.comparingDouble(i -> arr[i]));

Note that this is an optional, as the array could be empty. Also, when there are multiple minimums, it is not specified which one's index it will return. In the implementation that I'm using (OpenJDK 17), it returns the first one's index.

If you want to control which minimum's index you get, you can do:

Optional<Integer> minIndex = IntStream.range(0, arr.length).boxed().reduce(
    // gets the first one's:
    (a, b) -> arr[a] <= arr[b] ? a : b
    // gets the last one's:
    // (a, b) -> arr[a] < arr[b] ? a : b
);

CodePudding user response:

int index;
for (int i = 0; i < arr.length; i  ){
    double d = arr[i];
    if (d == min){
       index = i; 
       break;
    }
}

CodePudding user response:

Here's how it can be done without iterating over the array indices and trying to mimic for-loop with a stream.

And we can also grab the actual minimal value along the way.

For that we can use DoubleStream.collect() which expects three arguments:

  • Supplier<R> supplier - provides a mutable object which would serve as a container of data;
  • ObjDoubleConsumer<R> accumulator - determines how stream elements should be accumulated in the mutable collector provided by the supplier;
  • BiConsumer<R,R> combiner - combines partial results while executing the stream in parallel.

As a mutable container which should be provided by the supplier we can use an array double[] (if you have a look at the source code of Collectors that are intended to accumulate primitive values, namely summingInt(), summingDouble(), etc. you would probably find some similarities).

double[] arr = {263.5, 393.75, 5.0, 289.75};
        
double[] min = Arrays.stream(arr)
    .collect(
        () -> new double[]{0, -1, -1},   // supplier
        (double[] res, double next) -> { // accumulator
            res[2]  ; // total count
            if (res[1] == -1 || res[0] > next) {
                res[0] = next;   // min value
                res[1] = res[2]; // corresponding index
            }
        },
        (left, right) -> {              // combiner
            if (left[0] > right[0]) {
                left[0] = right[0];
                left[1] = left[2]   right[1];
            }
            left[2]  = right[2];
        }
    );
        
System.out.printf("Min value is %s at index: %d", min[0], (int) min[1]);

Output:

Min value is 5.0 at index: 2
  • Related