简体   繁体   中英

List<List<Integer>> ArrayList initialization does not work with new operator Java

I have been struggling on this problem for two days. This problem comes from some problem I am doing. Basically, when I use

List<List<Integer>> temp = new ArrayList<>(result);

to create a new ArrayList copy of result, the result will change when I try to change temp within an advanced for loop. For example,

List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList<>());
List<List<Integer>> temp = new ArrayList<>(result);
int j = 0;
for (List<Integer> list: temp) {
    list.add(x[j]);
    j ++;
}

I did nothing to the result inside the loop but the result ends up with [[1]], which is the same as temp.

Why is this happening? Thanks a lot.

Update: thank everybody for answering my question. I learn the shallow copy was the reason. However, I still run into a similar problem. The result is updated while I try to change the temp in the following code:

List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList<>());
List<List<Integer>> temp = new ArrayList<>();
for (List<Integer> list: result) {
    list.add(10000);
    temp.add(new ArrayList(list));
}

I do not know why the result turns out to be [[10000]] as well as the temp. Is there anything wrong with the add method like temp.add(new ArrayList(list))?

This is happening because the List<List<Integer>> temp = new ArrayList<>(result); statement copies only the top-level list. It will be the new list that contains references to the original items (aka sublists) from the original result .

You can fix this with a deep copy:

List<List<Integer>> temp = new ArrayList<>(); // empty list
for (List<Integer> sublist : result) {
    temp.add(new ArrayList<Integer>(result)); // copying a sublist and adding that
}

This is not surprising because you have only one list to iterate upon. If you add a second list you will see a second digit coming in.

int[] x = new int[]{1,2,3,4,5}; 

    List<List<Integer>> result = new ArrayList<>();
    result.add(new ArrayList());
result.add(new ArrayList());
    List<List<Integer>> temp = new ArrayList<>(result);
    for (Integer xx: x) {
        result.add(new ArrayList(xx));
    }
    System.out.println(result.toString());

If you try this code it will display you:

[[1],[2]]

temp = new ArrayList<>(result) only does a shallow copy of result , ie it copies the "outer" list, but not its elements.

temp.get(0) == result.get(0) - and I don't mean equals - they are exactly the same instance.

As such, anything you add to temp.get(0) will also appear in result.get(0) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM