3

I'm trying to learn generics in Java, and I would've thought this method would work for finding the largest in an array:

  public static <T> T largestInArray(T[] inputArray){
    T largest = inputArray[0];
    for (int i = 1; i < inputArray.length - 1; i++){
      if (inputArray[i] > largest)
        largest = inputArray[i];
    }
    return largest;
  }

but I get an error saying: bad operand types for binary operator '>' How should I do this?

Derry
  • 371
  • 1
  • 13
  • The `>` operand can only be use for numbers (`int`, `double`, `long`, etc.). The wrapper classes for those types will be unboxed so those will work, but others won't. – nbrooks Aug 23 '17 at 02:00
  • The `>` in Java does not work with Object (generics). You need to use `Comparator` or `Comparable` to compare objects in the array. – tsolakp Aug 23 '17 at 02:01
  • For future questions, if something does not compile, please always give us the full error (stack trace) including the exact line number where the compiler complaints about your code. – Zabuzard Aug 23 '17 at 02:12

2 Answers2

12

You can only use comparison operators on numeric types. If you want to compare generic types, you'll have to ensure they implement Comparable, and call Comparable.compare():

public static <T extends Comparable<? super T>> T largestInArray(T[] inputArray) {
    //...
    if (inputArray[i].compareTo(largest) > 0) {
    //...
}

compareTo() will return 0 for equal values, < 0 if the target object has precedence, and > 0 if the argument has precedence.

Alternatively, you can use a custom Comparator instead of relying on the natural order:

public static <T> T largestInArray(T[] inputArray, Comparator<? super T> comparator) {
    //...
    if (comparator.compare(inputArray[i], largest) > 0) {
    //...
}

compare() works similar to compareTo() above.

Note that these are both already implemented as Collections helpers, which you can easily call by wrapping the array:

Collections.max(Arrays.asList(inputArray)/*, comparator*/)
shmosel
  • 49,289
  • 6
  • 73
  • 138
  • Maybe you should include something about how Java generics require you to state requirements up-front, unlike e.g. C++ templates that work on any type as long as the code of the template can compile against it. – HTNW Aug 23 '17 at 02:15
  • now is it OK that I put into the header: instead of >? – Derry Aug 23 '17 at 02:38
  • 1
    @Derry No, `Comparable` is a [raw type](https://stackoverflow.com/q/2770321/1553851) and should be avoided. At minimum, you need `>`. But the version in my answer will give [the most flexibility to the caller](https://stackoverflow.com/q/25779184/1553851). – shmosel Aug 23 '17 at 02:41
  • it did compile, but in that case, what would be a case that my code wouldn't? – Derry Aug 23 '17 at 03:20
  • 1
    @Derry I didn't say it wouldn't compile, just that it should be avoided. – shmosel Aug 23 '17 at 03:35
2

Since Java defines comparison operators >, <, >=, and <= only for numeric types, you cannot apply them to objects, including generic ones.

Instead, you need to tell the compiler that objects of T will implement Comparable<T> interface. You wouldn't be able to use >, but you would be able to do what you need by calling compareTo:

if (inputArray[i].compareTo(largest) > 0) // Replaces inputArray[i] > largest
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523