Common method to find index of max element in both Float and Integer array

Viewed 170

This is basically to avoid redundant code. I have two different arrays, one of Float type and one Integer type. I need to find index of maximum element in both the arrays which is easy to do as I can write two different methods, one for comparing float and one for comparing Integers.

What am trying to do improve is to write just one common method which can take in either of the array as argument and can return me the max index. What I have tried unsuccessfully so far is:

private static int findMaxIndex(Object [] arr){
        int maxIndex =(int) IntStream.range(0,arr.length)
                  .boxed()
                  .max(Comparator.comparingInt(i -> arr[i])) // getting compiler error here
                  .map(max->arr[max])
                  .orElse(-1);
        
        
        return maxIndex;
    }

and am looking to call this method like this:

Float [] a = {0.3f, 0.5f, 0.9f, 0.7f, 0.1f};
Integer []b = {3000, 250, 100, 2000, 2000, 10246};

int maxIndexFloatArray = findMaxIndex(a);
int maxIndexIntegerArray = findMaxIndex(b);

Am pretty sure there are easier ways to do this, but am a bit rusty now in hands on java code. Hope this explains the question correctly.

5 Answers

lambda with reduce comparing Comparables

private static <T extends Comparable<? super T>> int findMaxIndex(T[] arr) {
  return IntStream.range(0, arr.length)
      .reduce((l, r) -> arr[l].compareTo(arr[r]) < 0 ? r : l).orElse(-1);
}

for multiple max values the index of the first is returned
if You need the index of the last max value change the < to <=
arr can be empty but may not contain null values

You could do it old fashioned:

private <T> int findMaxIndex(T[] arr, Comparator<T> comparator){
        int maxIndex= 0;
        T currMax = arr[0];
        for (int i=1;i<arr.length;i++){
            if (comparator.compare(currMax,arr[i])<0){
                currMax = arr[i];
                maxIndex = i;
            }
        }
        return maxIndex;
    }

And then call it like:

private int getMaxFloatIndex(Float[] floatArr){
        return findMaxIndex(floatArr,Float::compareTo);
    }

Grabbing the inheritance hierarchy "from top", I would propose Comparable<X> as the input type for findMaxIndex. It is the most general type of object, of which you can distinguish a "max element":

private static <X extends Comparable<X>> int findMaxIndex(final X[] arr) {
    return IntStream.range(0, arr.length)
           .boxed()
           .max(
             (Integer idx1, Integer idx2) -> arr[idx1].compareTo(arr[idx2])
           )
           .orElse(-1);
}

For simplicity: Hoping/assuming arr is nor null nor contains null elements! ;) (otherwise: NPE!)

...to use it like:

Float[] a = { 0.3f, 0.5f, 0.9f, 0.7f, 0.1f };
Integer[] b = { 3000, 250, 100, 2000, 2000, 10246 };
System.out.println(findMaxIndex(a));
System.out.println(findMaxIndex(b));

Prints:


2
5
 <T extends Number & Comparable<T>> int findMaxIndex(T[] arr)

This can find the index of the maximal value based on Number, the interface of all numeric types, wrapper classes and atomic wrappers.

Also a findMax might so be made. Without the numeric aspect, just Comparable suffices, say for a String[].

This one should do the trick:

private static <T extends Number & Comparable<T>> int findMaxIndex(T[] array) {
    if (array == null || array.length == 0) return -1;
    int largest = 0;
    for (int i = 1; i < array.length; i++) {
        if (array[i].compareTo(array[largest]) > 0) largest = i;
    }
    return largest;
}

You literally tell the compiler that your generic parameter T should be both a Number and Comparable to the same type.

Related