Iterating generic array of any type in Java
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.