开发者

Iterating generic array of any type in Java

If there is an instance of Java Collection which may carry primitive type, generic array, and/or iterable collection, I want to treat the generic array as Iterable collection, but how? e.g. the following pseudo java code

List<?> list1; 
list1.add(new int[2]); 
list1.add(new String[3]); 
list1.add(new ArrayList());
for (Object e : list1){
    if (e instanceof Iterable){ 
        //The int[2] and String[3] will not fall in this case that I want it be
        //Iterate within e
    }
}

Please advise how to make the int[2] and String[3] fall in t开发者_Go百科he case.

Thanks & regards, William


Use Array class from reflection package:

    final List<Object> list = new ArrayList<Object>();
    list.add(new int[] { 1, 2 });
    list.add(new String[] { "a", "b", "c" });
    final List<String> arrayList = new ArrayList<String>();
    arrayList.add("el1");
    list.add(arrayList);

    for (Object element : list) {
        if (element instanceof Iterable) {
            for (Object objectInIterable : (Iterable) element) {
                System.out.println(objectInIterable);
            }
        }
        if (element.getClass().isArray()) {
            for (int i = 0; i < Array.getLength(element); i++) {
                System.out.println(Array.get(element, i));
            }
        }
    }


Within your loop, you could use the appropriate array operand for instanceof.

For int[]:

if (e instanceof int[]) {
   // ...
}

For Object arrays (including String[]):

if (e instanceof Object[]){
    // ...
}

Alternatively, when adding your arrays to your master List, you could wrap each one in Arrays.asList(). In that case, you could use the List<List> generic instead of the wildcard generic List<?> and avoid the need to check the data type with instanceof. Something like this:

List<List> list1; 
list1.add(Arrays.asList(new int[2])); 
list1.add(Arrays.asList(new String[3])); 
list1.add(new ArrayList());
for (List e : list1){
    // no need to check instanceof Iterable because we guarantee it's a List
    for (Object object : e) {
        // ...
    }
}

Anytime you're using instanceof and generics together, it's a smell that you may be doing something not quite right with your generics.


You can't add things to a List<?>. If you want a list of heterogeneous things, use a List<Object>.

However, since you want to iterate over the things in your list, why not use a List<Iterable<Object>>? To add an array, use Arrays.asList(myarray) to get something that implements Iterable from it.

final List<Iterable<? extends Object>> list1 = new ArrayList<Iterable<? extends Object>>();

list1.add(Arrays.asList(new int[2]));
list1.add(Arrays.asList(new String[3])); 
list1.add(new ArrayList<Integer>());

for (final Iterable<? extends Object> e : list1) {
    for (final Object i : e) {
        // ...
    }
}

If you want to store non-iterable things in your list too, then you'll need to use List<Object> and the instanceof check, but you can still use Arrays.asList() to turn arrays into iterables, avoiding the need to handle arrays as a special case.


Arrays do not implement the Iterable interface.

public class StackOverflow
{
    public static void main(final String[] argv)
    {
        display(new int[0].getClass());
    }

    private static void display(final Class clazz)
    {
        final Class   superClass;
        final Class[] interfaces;

        superClass = clazz.getSuperclass();

        if(superClass != null)
        {
            display(superClass);
        }

        System.out.println(clazz.getCanonicalName());
        interfaces = clazz.getInterfaces();

        for(final Class iface : interfaces)
        {
            display(iface);
        }
    }
}

Output:

java.lang.Object
int[]
java.lang.Cloneable
java.io.Serializable

You can use isArray() on the class to see if it is an array:

public class StackOverflow
{
    public static void main(final String[] argv)
    {
        List<Object> list1;

        list1 = new ArrayList<Object>();
        list1.add(new int[2]);
        list1.add(new String[3]);
        list1.add(new ArrayList());

        for(Object e : list1)
        {
            if(e instanceof Iterable)
            {
                System.out.println("Iterable");
            }

            if(e.getClass().isArray())
            {
                System.out.println("array");
            }
        }
    }
}


public class IterTest {
    public static void main(String[] args) {
        ArrayList list1 = new ArrayList();

        list1.add(new int[] { 0, 1, 2 });
        list1.add(new String[] { "SA_0", "SA_1", "SA_2" });
        list1.add(Arrays.asList(new String[] { "L_0", "L_1", "L_2" }));

        for (Object e : list1) {
            if (e instanceof Iterable) {
                iterate((Iterable) e);
            } else if (e.getClass().isArray()) {
                iterateArray(e);
            }
        }
    }

    private static void iterateArray(Object e) {
        Class type = e.getClass().getComponentType();
        if (!type.isPrimitive())        { iterate((Object[])  e); }
        else if (type == boolean.class) { iterate((boolean[]) e); }
        else if (type == double.class)  { iterate((double[])  e); } 
        else if (type == float.class)   { iterate((float[])   e); } 
        else if (type == short.class)   { iterate((short[])   e); } 
        else if (type == long.class)    { iterate((long[])    e); } 
        else if (type == char.class)    { iterate((char[])    e); }
        else if (type == byte.class)    { iterate((byte[])    e); } 
        else if (type == int.class)     { iterate((int[])     e); } 
    }

    static void iterate(Iterable  a) { for (Object  e : a) { print(e); } }
    static void iterate(Object[]  a) { for (Object  e : a) { print(e); } }
    static void iterate(boolean[] a) { for (boolean e : a) { print(e); } }
    static void iterate(double[]  a) { for (double  e : a) { print(e); } }
    static void iterate(float[]   a) { for (float   e : a) { print(e); } }
    static void iterate(short[]   a) { for (short   e : a) { print(e); } }
    static void iterate(long[]    a) { for (long    e : a) { print(e); } }
    static void iterate(char[]    a) { for (char    e : a) { print(e); } }
    static void iterate(byte[]    a) { for (byte    e : a) { print(e); } }
    static void iterate(int[]     a) { for (int     e : a) { print(e); } }

    static void print(Object o) { System.out.println(o); }
}


Use generics

public void printArray(T[] someArray) {
    for (T t : someArray)
        System.out.println(t);        
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜