This question already has answers here:
Can a primitive value be considered an object in java?
(4 answers)
Closed 6 years ago.
I'm trying to implement my sort method, which takes a generic E[] as an argument, upon my int[]. I receive the error:
The method sort(E[]) in the type HeapSort is not applicable for the arguments (int[]).
My code is as follows:
public <E extends Comparable<E>> void sort(E[] array){
//my code
}
public static void main(String[] args){
int[] arr = new int[30];
for(int rep = 0; rep < arr.length; rep++){
arr[rep] =(int )(Math.random() * 100 + 0);
}
System.out.println("The unsorted Array: ");
System.out.println(sort(arr).toString());
}
Any ideas as to why I get this error? All help appreciated! Thank you!
A primitive type can't replace a generic type parameter (and even if it could, it couldn't satisfy your extends Comparable<E> type bound, since primitive types don't extend any class and don't implement any interface).
You can replace your int[] with an Integer[] and it will work.
Beside that error, sort(arr) doesn't return anything, so you can't execute toString on it.
You can replace it with :
new HeapSort ().sort(arr); // you must create an instance of the class that contains
// the sort method in order to call it
System.out.println(Arrays.toString(arr));
lets look at what you wrote there.
public <E extends Comparable<E>> void sort(E[] array)
this is a method called sort. it has generic parameter with a constraint. The constraint is that whatever the generic parameter you have put in, it must implement Comparable.
int doesn't implement Comparable, in fact int doesn't implement anything.
Java generics don't work with primitive types at all. Generic constraints only limit you farther.
Related
I am trying to write a method that will find the difference between elements of two arrays of the same length and here is what I did until now:
public static <T extends Object> T method(T[] array,T[] array1){
T[]difference;
difference = new T[array.length]; //error :generic array creation
for(int i=0;i<array.length;i++){
difference[i]=array[i]-array1[i]; //error:bad operand types for binary operator
}
return (T)difference;
}
but it constantly returns to me a message that i wrote next to the line of the code that it refers to
There are two problems with your code:
Java doesn't support generic array creation. You can get round this by creating an array of Objects and then casting.
The bigger problem is that java doesn't support operator overloading, and subtraction (i.e. -) is only supported by primitive types. This is compouded by the fact that generics doesn't support primitive types, which makes what you're trying to do impossible on its own.
To get round these problems, you'd need to do a number of things:
Don't use primitives, but you can used boxed types instead (so instead of int you'd use Integer, etc.).
You need to tell your function how to find the difference between two objects of the required type. You can achieve this by defining a 'Subtractor' interface.
I'd also suggest using lists instead of arrays, as these handle generics much more nicely. You can easily convert between lists and arrays afterwards if needed.
So, as a skeleton of a solution, here's what I'd propose:
Define a generic interface for finding differences:
interface Subtractor<T> {
T subtract(T a, T b);
}
Rewrite your method to use lists, and to take a subtractor as an argument:
public static <T> List<T> difference(
List<? extends T> listA, List<? extends T> listB, Subtractor<T> subtractor) {
int resultSize = Math.min(listA.size(), listB.size());
List<T> result = new ArrayList<>(resultSize);
for(int i=0; i<resultSize; ++i) {
result.add(subtractor.subtract(listA.get(i), listB.get(i)));
}
return result;
}
Define subtractor implementations for the types you want to be able to use the method with:
class IntSubtractor implements Subtractor<Integer> {
#Override
Integer subtract(Integer a, Integer b) {
return Integer.valueOf(a.intValue() - b.intValue());
}
}
Use your method. You can use Arrays.asList for turning arrays into lists, but you can't use arrays of primitives unfortunately.
Integer[] a = new Integer[]{5,6,7,8};
Integer[] b = new Integer[]{1,2,3,4};
Integer[] c = difference(Arrays.asList(a), Arrays.asList(b), new IntSubtractor())
.toArray(new Integer[4]);
I assume that your array values are numbers. It is difficult to provide a general solution. But I would say this might work for your case:
public static <T extends Number> Number[] method(T[] array, T[] array1){
Number[]difference = new Number[array.length];
for(int i=0; i< array.length; i++){
difference[i]= Double.valueOf(array[i].doubleValue() - array1[i].doubleValue());
}
return difference;
}
This question already has answers here:
When to use generic methods and when to use wild-card?
(9 answers)
Closed 7 years ago.
While on a quest on understanding about Java Generics, I've come across this:
public static <T extends Number> int sumListElems(List<T> list){
int total = 0;
for(Number n: list)
total += n.intValue();
return total;
}
Suppose I have the following method that adds the elements of a List, restricted to Lists that holds a Number.
But what's the difference of that code to this one:
public static int sumListElems(List<? extends Number> list){
int total = 0;
for(Number n: list)
total += n.intValue();
return total;
}
Both of them compiles and executes as expected. What are differences between those two? Aside from the syntax? When would I prefer using the wildcard over the former?
Well, yes, using the wildcard approach, I can't add a new element on the list except null, or it won't compile. But aside from that?
No difference in this case. For more complex signatures, you may need to reuse the defined type so defining it is needed. Something like:
public static <T extends Number> void foo(T bar, List<T> myList)...
This guarantees not only that both bar and the elements of myList extend Number, but they are of the same type. You could not positively enforce that with the other syntax.
I've been relearning Java after a long time, and I'm trying out writing some sorting algorithms. The (rather outdated) textbook I have uses the Comparable interface to sort objects. Since Comparables are now generic types, doing this gives me a lot of warnings about raw types when compiling. After some research, it looks like I can do something like, for example:
public class Sorting
{
public static <T extends Comparable<T>> void quickSort(T[] list, int start, int end)
{
/*...*/
while((list[left].compareTo(list[pivot]) < 0) && (left != right)) // for example
left++;
/*...*/
}
}
The problem with this is that the naive way of calling this method does not work:
public class SortingTest
{
public static void main(String[] args)
{
// Produces an error, cannot create arrays of generic types
Comparable<Integer>[] list = new Comparable<Integer>[100];
/* fill the array somehow */
Sorting.quickSort(list, 0, 99);
}
}
It is illegal to create an array of generic types in Java. The problem only gets worse if I try to implement a merge sort, since that requires creating arrays of Comparable types inside the merge sort method itself.
Is there any way to handle this situation elegantly?
Note that T extends Comparable<T>. It doesn't have to be Comparable<T>.
So you could, for example, create an array of Integers, because Integer implements Comparable<Integer>.
Integer[] list = new Integer[100];
/* fill the array somehow */
Sorting.quickSort(list, 0, 99);
You have to make an array of Object and then cast to an array of T. Note that this will create a compiler warning.
I have written sorting methods for an array of comparables, insertion, merge, and selection, I've done this by altering code I had before from sorting an int array, and I just changed things from int to Comparable. However, When I was doing it for int arrays, I knew very well how to actually use the method, for example this is my my selection sort for ints:
public void selectionSort(int[] list){
for (int i=0;i<list.length;i++){
for (int si=i;si<list.length;si++){
if (list[si]<list[i]){
int temp=list[i];
list[i]=list[si];
list[si]=temp;
}
}
}
}
and this is the code which ends up using this method:
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int numItems,searchNum,location;
Sorts sort=new Sorts();
int[]test;
System.out.print("Enter the number of elements: ");
numItems=in.nextInt();
test=new int[numItems];
for (int i=0;i<test.length;i++){
test[i]=(int)(100*Math.random());
}
System.out.println("Unsorted: ");
displayArray(test);
sort.selectionSort(test);
System.out.println("Sorted: ");
displayArray(test);
and everything works fine, but for my comparable selection sort, I have this code:
public static void selectionSort(Comparable[] list){
for (int i=0;i<list.length;i++){
for (int si=i;si<list.length;si++){
if (list[si].compareTo(list[i])<0){
Comparable temp=list[i];
list[i]=list[si];
list[si]=temp;
}
}
}
}
but when I get to writing the code to test out this method, I just have no idea how to approach it, I don't know how I can make an array of Comparable interfaces, the concept is just so confusing for me and I can't find a way to make it work.
Integer, for instance, implements Comparable, so it's legal to write:
Comparable[] list = new Comparable[3];
list[0] = Integer.valueOf(3);
list[1] = Integer.valueOf(2);
list[2] = Integer.valueOf(3);
You can see all the implementors of Comparable in the standard JDK by looking at the JavaDoc.
The trouble is (and you should see some compiler warnings about this), you can't both specify the generic parameter for Comparable and make an array of the parameterized object, that is, it's not legal to write:
Comparable<Integer>[] list = new Comparable<Integer>[3];
Even if it were legal to write that, you'd run into a new issue, since you need the concrete type to use in the Comparable<T> test. Comparable<T> requires a comparison to an object of type T (the method is int compareTo(T o)). In essence, your code only works because it's unparameterized (T is implicitly Object, everything extends Object), but you're losing some compile-time safety checks along the way.
It might make more sense to parameterize your input by an array of generic parameterized Comparable objects rather than as an array of Comparable. Writing this using generics is a little bit tricky, the method prototype would look something like:
public static void <T extends Comparable<T>> selectionSort(T[] list) {
// legal to call list[k].compareTo, because `T` is guaranteed to be `Comparable`
}
Notably, this will work for any non-primitive object type T that implements Comparable<T>, such as an Integer[] or Double[], but not an int[].
public class MergeSort
{
/**
* #param a Array to be sorted.
* #param n Last element to be sorted.
* #return void.
*/
public static <T extends Comparable<T>> void sort(T[] a, int n)
{
}
/**
* #param inp Input Array.
* #param out Output Array.
* #param first First index.
* #param mid Middle index.
* #param last Last index.
* #return void.
*/
private static <T extends Comparable<T>>
void merge(T[] inp, T[] out, int first, int mid, int last)
{
}
}
Hello everyone I need some help.
The above is the outline my professor gave us. My problem is I want to create a, T[] b , array in the sort method so I can reuse the two arrays 'a' and 'b' when I pass them to the merge method. Instead of creating a temp array in merge everytime I call it. I've tried
T[] b = (T[]) new Object[n];
And the class will compile but when I call the sort method from my main class with an Integer array I get:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
What can I do?
Any help would be much apreciated and if I missed this answer anywhere, my apoligies. I've been searching for the most part of the day. Thank You!
Well, the short answer is that in Java, arrays and generics don't play together very nicely.
As you already know, Java generics are implemented using type erasure, which means that while at compile time the type may be <T extends Comparable<T>>[], at runtime the type is erased to its lower bound, which in this case is Comparable[] (using the raw type). The type of T[] is not actually erased to Object[] unless that actually is the lower bound of the generic constraint.
The upshot of this is that it should be safe to say:
#SuppressWarnings("unchecked")
T[] b = (T[]) new Comparable<?>[n];
And everything should work as you expect.
Note that there are actually a lot more caveats you should be aware of if you try to mix arrays and generics. For example, you can implement covariance and contravariance with generics by using generic wildcards (e.g. <? extends T> and <? super T>), but arrays in Java implement covariance natively (and just throw ArrayStoreException when you try to invalidate their type invariants). So if you have the ability to switch from an array to generic type (ArrayList<T> for example will probably do what you want), then you'll find things go a lot more smoothly.
You may also find these links useful:
Can I create an array whose component type is a concrete parameterized type?
How can I work around the restriction that there are no arrays whose component type is a concrete parameterized type?
Since Object cannot be cast to T
T b = (T) new Object();
Thus this cannot not true either
T[] b = (T[]) new Object[n];
You can look at how Collection.toArray(T[] a) is implemented to create a new array of type T.