From Collection to array

The Collection interface, root of the Java Collection hierarchy, does not support cloning. That means that we can clone a concrete class, but we can't do it if we don't know the actual type of the collection.

We can overcome this issue by a couple of overloaded Collection.toArray() methods.

If we have an heterogeneous Collection, we can convert it to an array of Object, and then accessing any element checking what is its real type:
Collection<Object> oc = new HashSet<Object>();
oc.add(42);
oc.add("Deep Thought");
// ...

Object[] oi = oc.toArray();

for(Object o : oi) {
    if(o instanceof Integer) {
        if((Integer)o == 42) {
            // ...
        }
    }
    else if(o instanceof String) {
        if(((String)o).startsWith("Deep")) {
            // ...
        }
    }
    // ...
}
We pay the handiness of having a tutti-frutti collection with the ugliness of checking the instance type before being able to use an element. The array copy can't do much more than keep the same behavior for its elements.

But using the same toArray() method when dealing with an homogeneous Collection is a pity.
Collection<Integer> ic = new HashSet<Integer>();
ic.add(42);
// ...

Object[] oa = ic.toArray();
if(oa.length > 0 && (Integer)oa[0] == 42) { // !!!
    // ...
}
We must cast the element to the right type even if we already know that each element of the array is of that specific type. We can avoid this by using the other toArray() overload:
Integer ia[] = new Integer[ic.size()]; // 1
ic.toArray(ia); // 2
if(ia.length > 0 && ia[0] == 42) {
    // ...
}
1. Allocate memory for the array
2. Pass the array to toArray(), it simply fills it with the elements in the collection.

If we pass to toArray() an array shorter than expected, it allocates memory for a new array of the right size. The most valuable information we are passing to toArray() is the type we want to be used.

But what if we pass a wrong array type? As you could suspect, an exception would be thrown.
Collection<String> ic = new HashSet<String>();
// ...

Integer[] ia = new Integer[ic.size()]; // mistake!
try {
    ic.toArray(ia); // exception
}
catch(ArrayStoreException e) {
    // ...
}

No comments:

Post a Comment