I have searched for this, but unfortunately, I don\'t get the correct answer.
class Helper {
public static T[] toArray(List list) {
This gist that I wrote gives a good solution to this problem.
Following siegi's suggestion on Atreys' answer, I wrote a constructor which finds the "nearest common ancestor" (NCA) class and uses that class to create the array. If checks for nulls and if the provided Collection is length 0 or all nulls, the default type is Object. It totally ignores Interfaces.
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Array;
import java.util.Iterator;
public class FDatum {
public T[] coordinates;
// magic number is initial size -- assume <= 5 different classes in coordinates
public transient HashSet classes = new HashSet(5);
public FDatum (Collection coordinates) {
// to convert a generic collection to a (sort of) generic array,
// we need to bend the rules:
// 1. default class T is Object
// 2. loop over elements in Collection, recording each unique class:
// a. if Collection has length 0, or
// if all elements are null, class T is Object
// b. otherwise, find most specific common superclass, which is T
// record all unique classes in coordinates
for (T t : coordinates) this.classes.add(t.getClass());
// convert to list so we can easily compare elements
List classes = new ArrayList(this.classes);
// nearest common ancestor class (Object by default)
Class NCA = Object.class;
// set NCA to class of first non-null object (if it exists)
for (int ii = 0; ii < classes.size(); ++ii) {
Class c = classes.get(ii);
if (c == null) continue;
NCA = c; break;
}
// if NCA is not Object, find more specific subclass of Object
if (!NCA.equals(Object.class)) {
for (int ii = 0; ii < classes.size(); ++ii) {
Class c = classes.get(ii);
if (c == null) continue;
// print types of all elements for debugging
System.out.println(c);
// if NCA is not assignable from c,
// it means that c is not a subclass of NCA
// if that is the case, we need to "bump up" NCA
// until it *is* a superclass of c
while (!NCA.isAssignableFrom(c))
NCA = NCA.getSuperclass();
}
}
// nearest common ancestor class
System.out.println("NCA: " + NCA);
// create generic array with class == NCA
T[] coords = (T[]) Array.newInstance(NCA, coordinates.size());
// convert coordinates to an array so we can loop over them
ArrayList coordslist = new ArrayList(coordinates);
// assign, and we're done!
for (int ii = 0; ii < coordslist.size(); ++ii)
coords[ii] = coordslist.get(ii);
// that's it!
this.coordinates = coords;
}
public FDatum (T[] coordinates) {
this.coordinates = coordinates;
}
}
Here are some examples of using it in jshell ("unchecked" class warnings removed for brevity):
jshell> FDatum d = new FDatum(new ArrayList(Arrays.asList((double)1, (Double)3.3)))
class java.lang.Double
NCA: class java.lang.Double
d ==> com.nibrt.fractal.FDatum@9660f4e
jshell> d.coordinates
$12 ==> Double[2] { 1.0, 3.3 }
jshell> d = new FDatum(new ArrayList(Arrays.asList((double)1, (Double)3.3, (byte)7)))
class java.lang.Byte
class java.lang.Double
NCA: class java.lang.Number
d ==> com.nibrt.fractal.FDatum@6c49835d
jshell> d.coordinates
$14 ==> Number[3] { 1.0, 3.3, 7 }
jshell> d = new FDatum(new ArrayList(Arrays.asList((double)1, (Double)3.3, (byte)7, "foo")))
class java.lang.Byte
class java.lang.Double
class java.lang.String
NCA: class java.lang.Object
d ==> com.nibrt.fractal.FDatum@67205a84
jshell> d.coordinates
$16 ==> Object[4] { 1.0, 3.3, 7, "foo" }