14

I would like to take a passed List that I know is homogeneous and from it create an array of the same type as the elements within it.

Something like...

List<Object> lst = new ArrayList<Object>;

lst.add(new Integer(3));

/// somewhere else ...

assert(my_array instanceof Integer[]);

4 Answers 4

20

The conversion would happen runtime, while the type is lost at compile time. So you should do something like:

public <T> T[] toArray(List<T> list) {
    Class clazz = list.get(0).getClass(); // check for size and null before
    T[] array = (T[]) java.lang.reflect.Array.newInstance(clazz, list.size());
    return list.toArray(array);
}

But beware that the 3rd line above may throw an exception - it's not typesafe.

Sign up to request clarification or add additional context in comments.

7 Comments

+1: It's fine as long as the type of the first element of the list is the same as or a superclass of the type of all the other list elements. That's a very sneaky assumption, but may well work given the constraints in the question.
indeed. the OP said "that I know is homogeneous", but that's something that shouldn't be "extralinguistic".
Fine for a List<String>. Completely useless for a List<Shape>
@finnw: That's why I made my comment about it being a sneaky assumption. The real problem is that the generic type is erased after compilation – there's just no way to get it at runtime – so you have to guess what the type of the array needs to be. Bozho's code does about the best you can do with sane amounts of effort; going through the list and working out the common supertype of all the elements would be safer, but it's stupidly awkward and in the case of the exact type in the question, unnecessary.
@Bozho, for example in a List<Shape> the first element could be a Rectangle while the second was an Ellipse2D.Double (which will not fit in a Rectangle[].)
|
1

This method is type safe, and handles some nulls (at least one element must be non-null).

public static Object[] toArray(Collection<?> c)
{
  Iterator<?> i = c.iterator();
  for (int idx = 0; i.hasNext(); ++idx) {
    Object o = i.next();
    if (o != null) {
      /* Create an array of the type of the first non-null element. */
      Class<?> type = o.getClass();
      Object[] arr = (Object[]) Array.newInstance(type, c.size());
      arr[idx++] = o;
      while (i.hasNext()) {
        /* Make sure collection is really homogenous with cast() */
        arr[idx++] = type.cast(i.next());
      }
      return arr;
    }
  }
  /* Collection is empty or holds only nulls. */
  throw new IllegalArgumentException("Unspecified type.");
}

Comments

0
java.lang.reflect.Array.newInstance(Class<?> componentType, int length)

Comments

0

If you need to dynamically create an array based on a type known only at runtime (say you're doing reflection or generics) you'll probably want Array.newInstance

1 Comment

you can't downvote and not explain why. This sounds like the solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.