0

I'm trying to create a generic Intersection function that receives two arrays, the function would return an array with the commonality. The following is an example using what I currently have.

public static <T> T[] Intersection(T[] v1, T[] v2) {
    HashSet<T> set = new HashSet<>();
    set.addAll(Arrays.asList(v1));
    set.retainAll(Arrays.asList(v2));

    T[] v3 = {};
    v3 = set.toArray(v3);
    return v3;
}

My issue with the code above is: T[] v3 = {} results in the following error Cannot create a generic array of T . If I change the code to the following I get a warning stating Type safety: Unchecked cast from Object[] to T[].

public static <T> T[] Intersection(T[] v1, T[] v2) {
    HashSet<T> set = new HashSet<>();
    set.addAll(Arrays.asList(v1));
    set.retainAll(Arrays.asList(v2));

    T[] v3 = (T[])set.toArray();
    return v3;
}

Is there a safe way to accomplish this?

ZNackasha
  • 755
  • 2
  • 9
  • 29
  • Why do you need to create an empty array at all? Just `return (T[]) set.toArray();` should be enough. The warning is just a warning; does it fail at runtime? – kaya3 Jan 31 '20 at 18:15
  • @kaya3 this correct but it still does not solve my problem. – ZNackasha Jan 31 '20 at 18:16
  • @Gilgamesh22 Its just a warning, your code will run fine with an unchecked cast... If youre extra worried, put the cast in a try/catch block and return null in the catch if there is an exception when casting it. – Quinn Jan 31 '20 at 18:17
  • 3
    Does this answer your question? [How to create a generic array in Java?](https://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java) – marcinj Jan 31 '20 at 18:18
  • The reason you get a warning is because in principle an `Object[]` might contain some things that are not of type `T`. In your code you know it can't, because of how the array is made, so the code *is* safe and Java's warning is overly cautious. I would just add a `@SuppressWarnings("unchecked")` annotation, and test to make sure nothing goes wrong at runtime. – kaya3 Jan 31 '20 at 18:22

2 Answers2

2

Arrays in java not castable in general. That is why all collections have 2 toArray methods: Object [] toArray () and <T> T[] toArray (T[] array). If you cant know the array type at runtime, you have to deal with Object[]. In your case you have v1 and v2 of the desired type, and thus can use Arrays.copyOf and typed toArray.

T[] v3 = set.toArray(Arrays.copyOf(v1, set.size()));
2

You can use Arrays.copyOf with 0 length to construct an array copying a type from another array.

public static <T> T[] Intersection(T[] v1, T[] v2) {
    HashSet<T> set = new HashSet<>(Arrays.asList(v1));
    set.retainAll(Arrays.asList(v2));
    return set.toArray(Arrays.copyOf(v1, 0));
}

Note that in general, you are better of not using generics with arrays, instead preferring Lists. Arrays interact really badly with generics. You can use Arrays.asList to create a List interface view for an array if you have an array.

public static <T> List<T> Intersection(Collection<? extends T> v1, Collection<? extends T> v2) {
    ArrayList<T> newList = new ArrayList<>(v1);
    newList.retainAll(new HashSet<>(v2));
    return newList;
}
Konrad Borowski
  • 11,584
  • 3
  • 57
  • 71