I have this code that is meant to count all duplicates in any given generic type list
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] x = new int[]{1, 2, 3, 1, 4, 3};
System.out.println(util.countAllDuplicates(x));
}
}
class util {
public static <T> int countAllDuplicates(T[] myLis){
// public static int countAllDuplicates(int[] myLis){
int duplicates = 0;
for (int i = 0; i < myLis.length; i ) {
for (int j = i 1; j < myLis.length; j ){
if (myLis[i] == (myLis[j])) {
duplicates ;
}
}
}
return duplicates;
}
}
If I were to uncomment the header that takes int[]
instead of T[]
, then it works perfectly fine.
However, once I try to use a generic type I get the error:
java: method countAllDuplicates in class util cannot be applied to given types;
required: T[]
found: int[]
Why is this? Shouldn't int[]
be considered as T[]
?
I suspect the issue is in the method header but after looking at multiple resources I'm still unsure how to fix it.
Futhermore, I tried to instead use an ArrayList
instead:
import java.util.ArrayList;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> x = new ArrayList<>(Arrays.asList(1, 2, 3, 1, 4, 5, 4));
System.out.println(util.countAllDuplicatesArrayList(x));
}
}
class util {
public static int countAllDuplicatesArrayList(ArrayList myLis){
int duplicates = 0;
for (int i = 0; i < myLis.size(); i ) {
for (int j = i 1; j < myLis.size(); j ){
if (myLis.get(i).equals(myLis.get(j))) {
duplicates ;
}
}
}
return duplicates;
}
}
and it magically works! (although I do get a warning that I am using a raw parameterized class which isn't ideal)
So three questions:
how is using a raw parameterized class allowed but not using a generic list type- shouldn't it be fundamentally the same thing other than the slight caveat that one can't use primitive types?
how would I get the method to work with generic list types?
If I were to use the
ArrayList
method, how would I avoid theRaw use of parameterized class 'ArrayList'
warning?
Any help would be greatly appreciated
CodePudding user response:
Well, a primitive array is kind of special. An int[]
itself is an object (JLS § 10), but its component type (JLS § 10) is not. That's why assigning an int[]
to T[]
is not possible. If your occurrences of int[]
were replaced by Integer[]
, it would also work.
It's better to use List
s alltogether instead of arrays: List
s are more flexible, as they can be resizable and give you more control over who can access its components, and in some cases, arrays don't work well with generics.
First of all, raw types shouldn't be used. A lot of the aspects of raw types are discussed in this Stack Overflow post.
Your
countAllDuplicatesArrayList
can be easily fixed by providing the type parameter:ArrayList<T>
.Always provide the necessary type arguments.
In short, the method declaration should be like this:
public static <T> int countAllDuplicatesArrayList(List<T> myLis) {
...
}
Further notes:
- You should follow the Java Naming Conventions: class names are written in PascalCase, so
util
should beUtil
. - I have used
List<T>
as parameter, instead ofArrayList<T>
. This post discusses why you should do this.
CodePudding user response:
int is a primitive data type that cannot be used in this case. If you use Integer instead, your initial code works:
Integer[] x = new Integer[] { 1, 2, 3, 1, 4, 3 };
See https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#instantiate