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

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.