Java ArrayList ArrayList
Następujący kod wyjścia
[[100, 200, 300], [100, 200, 300]].
Jednak oczekuję
[[100, 200, 300], [100, 200]],
Gdzie się mylę?
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();
inner.add(100);
inner.add(200);
outer.add(inner);
outer.add(inner);
outer.get(0).add(300);
System.out.println(outer);
}
3 answers
Dodajesz odwołanie do tego samego wewnętrznego ArrayList
dwa razy do zewnętrznej listy. Dlatego, gdy zmieniasz wewnętrzną listę (dodając 300), widzisz ją w " obu " wewnętrznych listach (gdy w rzeczywistości jest tylko jedna wewnętrzna lista, dla której dwa odwołania są przechowywane na zewnętrznej liście).
Aby uzyskać pożądany rezultat, należy utworzyć nową wewnętrzną listę:
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();
inner.add(100);
inner.add(200);
outer.add(inner); // add first list
inner = new ArrayList<Integer>(inner); // create a new inner list that has the same content as
// the original inner list
outer.add(inner); // add second list
outer.get(0).add(300); // changes only the first inner list
System.out.println(outer);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-05 20:48:14
This is what you have now
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();
Utworzy
outer -> []
inner -> []
Po
inner.add(100);
inner.add(200);
Twoja sytuacja wygląda jak
outer -> []
inner -> [100, 200]
Here comes confusing part
outer.add(inner);
outer.add(inner);
Które w rzeczywistości kopiują wartość inner
referencji, co oznacza, że wskazują na tę samą listę z inner
outer -> [ reference1 , reference2 ]
| |
+-------+ |
+---------------------+
↓
inner +-> [100, 200]
Co oznacza, że jeśli zmienisz stan listy posiadanej przez inner
będziesz mógł zobaczyć te zmiany używając reference1
i reference2
. To samo, jeśli zmienisz tę listę za pomocą innych referencje, więc kiedy używasz
outer.get(0).add(300);
get(0)
zwraca listę, do której można uzyskać dostęp również za pomocą inner
lub get(1)
i dodając nowy element tak, aby sytuacja wyglądała następująco
outer -> [ reference1 , reference2 ]
| |
+-------+ |
+---------------------+
↓
inner -> [100, 200, 300]
Dlatego kiedy drukujesz outer
widzisz
[[100, 200, 300], [100, 200, 300]].
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
from get(0) from get(1)
To, czego potrzebujesz, to utworzyć osobną listę, aby reference1
i reference2
wskazywały na dwie oddzielne listy. Więc potrzebujesz czegoś takiego jak
outer -> []
inner1 -> [100, 200]
inner2 -> [100, 200]
Które zostaną później zorganizowane do
outer -> [ reference1 , reference2 ]
| |
+------+ |
↓ |
inner1 -> [100, 200] |
|
+--------------------+
↓
inner2 -> [100, 200]
You can do it this sposób
List<List<Integer>> outer = new ArrayList<List<Integer>>();
List<Integer> inner1 = new ArrayList<Integer>();
List<Integer> inner2 = new ArrayList<Integer>();
inner1.add(100);
inner1.add(200);
inner2.add(100);
inner2.add(200);
outer.add(inner1);
outer.add(inner2);
outer.get(0).add(300);
System.out.println(outer);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-11 16:15:12
Polecenie outer.add(inner)
dodaje odniesienie do inner
, a nie jego kopię.
Więc, kiedy dodajesz dwa odniesienia do inner
do ArrayList outer
, dodajesz dwa z tego samego. Modyfikowanie inner
przez outer.get(0)
również modyfikuje wartość w outer.get(1)
, ponieważ odnoszą się one do tej samej rzeczy.
Jeśli utworzysz kopię inner
i użyjesz jej zamiast, będziesz miał dwie różne instancje i będziesz mógł je modyfikować oddzielnie. Można to zrobić za pomocą prostego polecenia:
outer.add(new ArrayList<[var type]>(inner));
The instrukcja dla new ArrayList(inner)
tworzy nowy ArrayList
z zawartością inner
wewnątrz - ale nie używa tej samej instancji co inner
. W ten sposób zachowasz zawartość, ale nie zachowasz zduplikowanego odniesienia.
Dodając nową kopię zamiast referencji, możesz zmodyfikować kopię bez modyfikowania tego, co możesz nazwać " oryginałem."
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-05 20:34:40