4

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?

Dan
  • 3,647
  • 5
  • 20
  • 26
zxwang
  • 51
  • 1
  • 4
  • 3
    Please update your question with a complete, runnable program which illustrates your problem. – tgdavies May 31 '22 at 05:54
  • https://stackoverflow.com/questions/189559/how-do-i-join-two-lists-in-java – Ravi Makwana May 31 '22 at 05:57
  • 1
    if `a.addAll(b)` doesn't work, you're doing something wrong. Please [edit] and share the code you're executing – azro May 31 '22 at 05:59
  • @azro All that matters is whether the outer list `a` is mutable or not, *and* whether the OP's input is what they really want to perform the transformation from. – Nikolas Charalambidis May 31 '22 at 06:23
  • 3
    `Arrays.asList` creates "*a fixed-size list*" as [documented](https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/Arrays.html#asList(T...)) - for the next question "*doesn't work*" could be more specific (how does it not work) but "*throws an error*" is not enough, at least mention the exception, even better, include its Stack Trace! – user16320675 May 31 '22 at 06:52
  • "*What's the difference*" --> `Arrays.asList()` =!= `new ArrayList<>()` - first is a **method**, second is a **constructor** - first returns a `List` (instance of `java.util.Arrays$ArrayList`, a nested class of `Arrays`), second creates an instance of `java.util.ArrayList` (not nested, different class as the first one, despite having the same name [unfortunately]) – user16320675 May 31 '22 at 06:58
  • As @user16320675 mentioned, `Arrays.asList creates "a fixed-size list"`. This means you can't modify it afterwards. – XtremeBaumer May 31 '22 at 07:03

3 Answers3

8

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 :

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.

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
2

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.

Dan
  • 3,647
  • 5
  • 20
  • 26
-2

You could avoid using the addAll function and iterate through b and add to a like shown below:

for(innerList:b){
   a.add(innerList);
}