Reputation: 2329
I am trying to figure out how to compare two items within a T[] array, here is what I have:
public static <T extends Comparable< ? super T>> T getLargest(T [] a, int low,
int high){
if(low>high)
throw new IllegalArgumentException();
T[] arrCopy = (T[]) new Object[high-low];
for(int i=low;i<high;i++){
if(a[i].compareTo(a[i-1])>0)
arrCopy[i]=a[i];
else
arrCopy[i]=a[i+1];
}
return arrCopy[0];
}
and then I get the error: Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
Any ideas on how I can resolve this?
Upvotes: 2
Views: 3785
Reputation: 31323
Just change new Object[high-low];
to new Comparable[high-low];
. Generics are erased to their lower bound, so T is erased to Comparable.
Upvotes: 0
Reputation: 38142
Use:
public static <T extends Comparable<? super T>> T max(final T[] data, int fromIndex,
int toIndex) {
return Collections.max(Arrays.asList(data).subList(fromIndex, toIndex));
}
Upvotes: 2
Reputation: 299048
You can assign the array like this:
@SuppressWarnings("unchecked")
T[] arrCopy = (T[]) Array.newInstance(a.getClass().getComponentType(), high-low);
Although the unchecked warning is necessary, this should actually be safe.
Btw, if you want to find the largest element in an array, here's a oneliner:
public static <T extends Comparable<T>> T max(final T[] data) {
return Collections.max(Arrays.asList(data));
}
For the complete problem you can use one of these two (they are equivalent):
public static <T extends Comparable<T>> T maxA(final T[] data,int from, int to) {
return Collections.max(Arrays.asList(Arrays.copyOfRange(data, from, to)));
}
public static <T extends Comparable<T>> T maxB(final T[] data,int from, int to) {
return Collections.max(Arrays.asList(data).subList(from, to));
}
Upvotes: 5
Reputation: 15259
There's no reason to assume that an array of Object
instances is fit for treatment as an array of Comparable
instances. You're forcibly casting Object
down to T
, which we expect extends Comparable
, but that unchecked assignment isn't even necessary here.
Instead, consider an implementation that does not copy any of the array:
public static <T extends Comparable<? super T>>
T getLargest(T[] a, int first, int last)
{
// Don't tolerate an empty range:
if (first >= last)
throw new IllegalArgumentException();
// Eventually checked by subsequent use of array index operator:
if (first < 0 || first >= a.length ||
last < 0 || last >= a.length)
throw new IndexOutOfBoundsException();
T largest = a[first];
while (++first != last)
{
final T candidate = a[first];
if (candidate.compareTo(largest) > 0)
largest = candidate;
}
return largest;
}
Alternately, use Collections#max()
, supplying your array viewed as a List
after passing it through Arrays#asList()
.
Upvotes: 2
Reputation: 5666
You get the error here:
T[] arrCopy = (T[]) new Object[high-low];
You cannot cast the mother object of all objects (java.lang.object) to anything that has java.lang.comparable as the lowest common denominator, so the exception is thrown. An object (as in java.lang.object) does not implement java.lang.comparable.
In your specific example, you would need to create an array of T (or at the very least java.lang.comparable).
Upvotes: 2
Reputation: 53694
not sure why you create an entire new array when you only care about 1 object, but the issue has nothing to do with generics. you can't cast an Object[]
to some more specific type like String[]
, just like you can't write String s = new Object()
.
seeing as you only care about the largest value, it would make much more sense to only track 1 value (the biggest value seen so far), not the entire array.
Upvotes: 2