10.3 Writing a Max Function
We've seen that Java provides a nice Collections.max
function for us. Collections
also includes other handy functions like min
, sort
, and reverse
.
In this chapter we'll see how we can write such functions ourselves.
Generic Functions (Warumup)
As a warmup suppose we want a function which picks a random item from an array. Some code is shown below:
And a sample program that uses this function is given below:
Next, we'll try to make it so that the pickRandom
function can work on any type of array.
Approach One: Generics
We can try to use Generics, as shown in the code below:
However, this code doesn't really make sense as written. The pickRandom
function is static, but we have to instantiate a RandomPicker
object to specify the generic type. That is, we'd need to do something like:
but we can't call static methods using an instance.
A fix for this is to make the pickRandom
function non-static, as shown below:
If we do this our code will work fine, but it's still very awkward to have to instantate a picker object.
Approach Two: Generic Static Methods
The correct and better approach is to make our static method generic. This is shown below:
This syntax is confusing (and it'll get worse later!). The way you can read public static <T> T pickRandom(T[] x)
is: "I am declaring a public static function that works on objects of type , it returns a T, it is called pickRandom, and it takes an array of Ts as its input.
After noting to Java that our static method is generic, we can call it without instantiating a RandomPicker
object as shown below:
Note that unlike generic classes, we don't need to specify the generic type when calling a generic static method (i.e. there's no <String>
after pickRandom
). The type is automatically inferred.
One minor annoyance is that our pickRnadom function will not work with arrays of primitive types, i.e. we can use int[]
, double[]
, float[]
.
There's no way around this, and in fact real Java libraries often have multiple functions, one for each primitive type. For example, there exists Arrays.sort(int[])
, Arrays.sort(double[])
, Arrays.sort(float[])
, etc. One day maybe Project Valhalla will fix this.
Writing our Max Function, Type Bounds
Using the idea of a generic static function, we can write our max function as follows:
There's one last problem, Java doesn't know that T
has a compareTo
method. We can fix this by adding a type bound to our generic type, as shown below:
This tells Java that T
, whatever it is, has to implement Comparable<T>
. If you try to pass an arary of objects into max that does not implement Comparable<T>
, you'll get a compile-time error.
The way to read public static <T extends Comparable<T>> T max(T[] items)
is: "I am declaring a public static function that works on objects of type , it returns a T, it is called max, and it takes an array of Ts as its input. Additionally, T has to implement Comparable."
Bonus: An Even Better Type Bound
In real industrial strength Java code, the correct way to specify our method is:
Last updated