1

In Java I want to convert a nested List which contains at the deepest level a uniform type into an multidimensional array of that type. For example, ArrayList<ArrayList<ArrayList<ArrayList<String>>>> into String[][][][]. I've tried several things and I only can obtain an array of objects like Object[][][][]. For 'simple lists' it seems that Apache Commons Lang does the work but I cannot figure out for nested cases.

Update:

In order to obtain a multidimensional array of Object type I'm using a recursive function so I cannot set the key type using toArray() see excerpt:

// the argument of this function is a (nested) list
public static Object convert(Object object) {

    Object[] result = null;
    List list = (List) object;
    if (list != null) {

        Object type = getElementType(list);
        if (type instanceof List) {

            int size = list.size();
            result = new Object[size];
            for (int counter = 0; counter < size; counter++) {

                Object element = list.get(counter);
                result[counter] = (element != null) ? convert(element) : null;
            }
        } else {
            result = list.toArray();
        }
    }

    return result;
}

private static Object getElementType(List list) {

    Object result = null;
    for (Object element : list) {
        if (element != null) {

            result = element;
            break;
        }
    }

    return result;
}
6
  • Neither your input nor your desired output are sufficiently clear. Please share more detail as to what you've tried already. Commented Dec 17, 2009 at 15:36
  • 1
    @seh: What the OP wants is to be able to create a T[][][][] (for example) out of a List<List<List<List<T>>>>, for any reference type T. Instead, he's getting Object[][][][]. Commented Dec 17, 2009 at 15:40
  • I was hung up by the phrase into an array list of primitive types. Apparently that really means "into a multidimensional array of primitive types". Commented Dec 17, 2009 at 15:43
  • Thanks Chris to rephrase my question, I already edited it using the coment of seh. Commented Dec 17, 2009 at 15:53
  • 1
    Since when is String a primitive? Since when can you store primitives in a Collection? Commented Dec 17, 2009 at 16:56

4 Answers 4

3

To create any kind of non-Object array, you need to pass a type key to the toArray method. This is because for generic types (e.g., ArrayList), the type argument is erased (so, at runtime, ArrayList<String> is treated as a plain ArrayList), whereas for arrays, the type is not.

It seems you already have the Object array creation sorted, so with that and the use of the type key, I think you're all sorted! :-)

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

2 Comments

For example, new ArrayList<String>().toArray() returns an Object[]. Passing in the type key, such as new ArrayList<String>().toArray(new String[0]) means that the return value is a String[]. You just need to figure out how to use this concept in your current code that's producing an Object[][][][].
I cannot set the type key because I'm using a recursive fuction to generate the nested List and then to convert it to multidimensional array of Objects
1

This is the way that someone suggested to solved for String type. Cast2(List<?>) returns the multidimensional array. It may be generalized to use the class type as parameter. Thank you for your comments.

static int dimension2(Object object) {

    int result = 0;
    if (object instanceof List<?>) {

        result++;
        List<?> list = (List<?>) object;
        for (Object element : list) {
            if (element != null) {
                result += dimension2(element);
                break;
            }
        }
    }

    return result;
}


static Object cast2(List<?> l) {

    int dim = dimension2(l);
    if (dim == 1) {
        return l.toArray(new String[0]);
    }

    int[] dims = new int[dimension2(l)];
    dims[0] = l.size();
    Object a = Array.newInstance(String.class, dims);
    for (int i = 0; i < l.size(); i++) {

        List<?> e = (List<?>) l.get(i);
        if (e == null) {
            Array.set(a, i, null);
        } else if (dimension2(e) > 1) {
            Array.set(a, i, cast2(e));
        } else {
            Array.set(a, i, e.toArray(new String[0]));
        }
    }
    return a;
}

Comments

0

hehe, heres a answer too but i dunno if that really helps:

List<ArrayList<ArrayList<ArrayList<String>>>> x = new ArrayList<ArrayList<ArrayList<ArrayList<String>>>>();

    public static void main(String[] args) throws MalformedURLException, IOException, SecurityException, NoSuchFieldException {

        Type t = ((ParameterizedType)(jdomTEst.class.getDeclaredField("x").getGenericType())).getActualTypeArguments()[0];  
        int[] dims = new int[t.toString().split("List").length];
        Object finalArray = Array.newInstance(String.class,  dims);

        System.out.println(finalArray);

    }

this prints: [[[[Ljava.lang.String;@4e82701e

looks pretty messy but i love reflections :)

1 Comment

The creation is not the problem, consider I have the nested list created and filled and now I want to transform it to a multidimensional array keeping the populated values of the original list.
0

You can use transmorph :

ArrayList<ArrayList<ArrayList<ArrayList<String>>>> arrayList = new ArrayList<ArrayList<ArrayList<ArrayList<String>>>>();

/// populate the list ...
[...]    

Transmorph transmorph = new Transmorph(new DefaultConverters());
String[][][][] array = transmorph.convert(arrayList, String[][][][].class);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.