I have two List<List<String>> and would like to concatenate them.
Here is my code:
List<List<String>> a = Arrays.asList(Arrays.asList("a", "b", "c"));
List<List<String>> b = Arrays.asList(Arrays.asList("d", "e", "f"));
a.addAll(b);
However, it doesn't work and throws an exception.
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
The code below works:
List<List<String>> a = new ArrayList<>();
a.add(Arrays.asList("a", "b", "c"));
List<List<String>> b = new ArrayList<>();
b.add(Arrays.asList("d", "e", "f"));
a.addAll(b);
What's the difference here?
Your attempt with a.addAll(b) works as long as the outer list a is mutable and you don't mind to modify it.
Mutable outer list:
List<List<String>> a = new ArrayList<>(List.of(
List.of("a", "b", "c"),
List.of("d", "e", "f")));
List<List<String>> b = new ArrayList<>(List.of(
List.of("h", "i", "j"),
List.of("k", "l", "m")));
a.addAll(b); // the 'a' will contain all the inner lists
a.forEach(System.out::println);
Immutable outer list
In case you want to preserve the former a and b lists and/or yield a new one, use java-stream:
List<List<String>> a = List.of(
List.of("a", "b", "c"),
List.of("d", "e", "f"));
List<List<String>> b = List.of(
List.of("h", "i", "j"),
List.of("k", "l", "m"));
List<List<String>> result = Stream.of(a, b)
.flatMap(Collection::stream)
.collect(Collectors.toList());
result.forEach(System.out::println);
Result
Both ways share the same output:
[a, b, c] [d, e, f] [h, i, j] [k, l, m]
Whether the inner lists are immutable or not doesn't matter for such combining.
Your code doesn't work because the Arrays.asList() returns
a fixed-size list backed by the specified array
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#asList(T...)
This means that when you try to add further elements, there is no space within the array representing the List; thus throwing anUnsupportedOperationException.
If you want to build List with specific elements and also be able to extend its size, then you should employ the class' Conversion Constructor by providing to it the lists returned by the asList() method.
List<List<String>> a = new ArrayList<>(Arrays.asList(new ArrayList<>(Arrays.asList("a", "b", "c"))));
List<List<String>> b = new ArrayList<>(Arrays.asList(new ArrayList<>(Arrays.asList("d", "e", "f"))));
a.addAll(b);
This way, both your outer and inner lists will behave as an actual List without throwing an UnsupportedOperationException when exceeding the original size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With