Wat is het verschil tussen
-
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); // Copy
-
List<Integer> list2 = Arrays.asList(ia);
, waarbij ia
een array van gehele getallen is?
Ik kwam erachter dat sommige bewerkingen niet zijn toegestaan in list2
. Waarom is het zo?
Hoe wordt het in het geheugen opgeslagen (referenties / kopie)?
Als ik de lijsten schud, heeft list1
geen invloed op de originele array, maar list2
wel. Maar toch is list2
enigszins verwarrend.
Hoe verschilt het opwaarderen van een ArrayList
naar een lijst van het maken van een nieuwe ArrayList
?
list1 differs from (1)
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
Antwoord 1, autoriteit 100%
-
Laten we eerst eens kijken wat dit doet:
Arrays.asList(ia)
Er is een array
ia
voor nodig en er wordt een wrapper gemaakt dieList<Integer>
implementeert, waardoor de originele array als een lijst beschikbaar is. Niets wordt gekopieerd en alles, er wordt slechts één wrapper-object gemaakt. Bewerkingen op de lijst-wrapper worden doorgegeven aan de oorspronkelijke array. Dit betekent dat als u de lijstwrapper schudt, de originele array ook wordt geschud, als u een element overschrijft, wordt het overschreven in de originele array, enz. Natuurlijk zijn sommigeList
-bewerkingen dat niet toegestaan op de wrapper, zoals het toevoegen of verwijderen van elementen uit de lijst, kunt u de elementen alleen lezen of overschrijven.Merk op dat de lijst-wrapper
ArrayList
niet uitbreidt – het is een ander soort object.ArrayList
s hebben hun eigen, interne array, waarin ze hun elementen opslaan, en kunnen de grootte van de interne arrays enz. wijzigen. De wrapper heeft geen eigen interne array, hij verspreidt alleen bewerkingen naar de array die eraan is gegeven. -
Aan de andere kant, als u vervolgens een nieuwe array maakt als
new ArrayList<Integer>(Arrays.asList(ia))
vervolgens maakt u een nieuwe
ArrayList
aan, die een volledige, onafhankelijke kopie is van de originele. Hoewel u hier de wrapper ook maakt met behulp vanArrays.asList
, wordt deze alleen gebruikt tijdens de constructie van de nieuweArrayList
en wordt deze daarna als afval verzameld. De structuur van deze nieuweArrayList
is volledig onafhankelijk van de originele array. Het bevat dezelfde elementen (zowel de originele array als deze nieuweArrayList
verwijzen naar dezelfde gehele getallen in het geheugen), maar het creëert een nieuwe, interne array die de verwijzingen bevat. Dus als je het schudt, elementen toevoegt, verwijdert enz., blijft de originele array ongewijzigd.
Antwoord 2, autoriteit 11%
Nou, dit komt omdat ArrayList
resulterend uit Arrays.asList()
niet van het type java.util.ArrayList
is.
Arrays.asList()
maakt een ArrayList
van het type java.util.Arrays$ArrayList
die java.util.ArrayList
, maar breidt alleen java.util.AbstractList
uit.
Antwoord 3, autoriteit 4%
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy
In dit geval, list1
is van het type ArrayList
.
List<Integer> list2 = Arrays.asList(ia);
Hier wordt de lijst geretourneerd als een List
Weergave, wat betekent dat het alleen de methoden aan die interface heeft. Vandaar waarom sommige methoden niet zijn toegestaan op list2
.
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
Hier zijn u een nieuwe ArrayList
maken. Je passeert het gewoon een waarde in de constructor. Dit is geen voorbeeld van gieten. Bij het gieten kan het er meer op uitzien:
ArrayList list1 = (ArrayList)Arrays.asList(ia);
Antwoord 4, Autoriteit 2%
Een verklaring met documentatie-referenties zou beter zijn voor iemand die op zoek is naar antwoord.
1. java.util.arrays
- Dit is een hulpprogramma met een hoop statische methoden om op gegeven array
- Aslist is een dergelijke statische methode die input array neemt en een object van java.util.arrays.arraylist retourneert. Dat is een statische geneste klas die abstractlist & lt; E & GT uitbreidt; welke op zijn beurt een lijst met lijstinterface implementeert.
- Dus Arrays.asList(inarray) retourneert een lijst-wrapper rond de invoerarray, maar deze wrapper is java.util.Arrays.ArrayList en niet java.util.ArrayListen het verwijst naar hetzelfde array, dus het toevoegen van meer elementen aan de List-ingepakte array zou ook van invloed zijn op de originele en we kunnen de lengte ook niet wijzigen.
te werken
2. java.util.ArrayList
-
ArrayList heeft een heleboel overbelaste constructors
public ArrayList() - // Returns arraylist with default capacity 10 public ArrayList(Collection<? extends E> c) public ArrayList(int initialCapacity)
-
Dus wanneer we het Arrays.asList geretourneerde object, dwz List(AbstractList) doorgeven aan de tweede constructor hierboven, zal het een nieuwe dynamische array creëren (deze arraygrootte neemt toe naarmate we meer elementen toevoegen dan de capaciteit en ook de nieuwe elementen hebben geen invloed op de originele array) oppervlakkig kopiëren van de originele array (ondiepe kopiebetekent dat het alleen over de referenties kopieert en geen nieuwe set van dezelfde objecten maakt als in de originele array)
Antwoord 5, autoriteit 2%
String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> namesList = Arrays.asList(names);
of
String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> temp = Arrays.asList(names);
De bovenstaande verklaring voegt de wrapper op de ingangsarray toe. Dus de methoden zoals toevoegen en verwijderen zijn niet van toepassing op het namenlijst van de lijstreferentieobject ‘.
Als u een element in de bestaande array / lijst probeert toe te voegen, krijgt u “Uitzondering in draad” Main “Java.lang.unsupportedOperationException”.
De bovenstaande bediening is readonly of viewing.
We kunnen niet uitvoeren of verwijder de bediening in lijstobject.
maar
String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.ArrayList<String> list1 = new ArrayList<>(Arrays.asList(names));
of
String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> listObject = Arrays.asList(names);
java.util.ArrayList<String> list1 = new ArrayList<>(listObject);
In de bovenstaande instructie heb je een concrete instantie van een Arrayclist-klasse gemaakt en een lijst doorgegeven als een parameter.
In dit geval, methoden toevoegen en Verwijderen zullen op de juiste manier werken, omdat beide methoden zijn van de klasse ArrayList, dus hier krijgen we geen niet-ondersteundeOperationException.
Wijzigingen aangebracht in het ARRAYLIST-object (methode toevoegen of verwijderen van een element in / van een arrayclist) zullen niet worden weerspiegeld in de oorspronkelijke java.util.list-object .
String names[] = new String[] {
"Avinash",
"Amol",
"John",
"Peter"
};
java.util.List < String > listObject = Arrays.asList(names);
java.util.ArrayList < String > list1 = new ArrayList < > (listObject);
for (String string: list1) {
System.out.print(" " + string);
}
list1.add("Alex"); // Added without any exception
list1.remove("Avinash"); // Added without any exception will not make any changes in original list in this case temp object.
for (String string: list1) {
System.out.print(" " + string);
}
String existingNames[] = new String[] {
"Avinash",
"Amol",
"John",
"Peter"
};
java.util.List < String > namesList = Arrays.asList(names);
namesList.add("Bob"); // UnsupportedOperationException occur
namesList.remove("Avinash"); // UnsupportedOperationException
Antwoord 6, autoriteit 2%
Allereerst is de klasse Arrays een hulpprogrammaklasse die een aantal hulpprogrammamethoden bevat om op Arrays te werken (dankzij de klasse Arrays. Anders hadden we onze eigen methoden moeten maken om op Array-objecten te werken)
asList() methode:
-
De methode
asList
is een van de hulpprogramma’s van de klasseArray
, het is een statische methode en daarom kunnen we deze methode bij de klassenaam aanroepen (zoalsArrays.asList(T...a)
)- Hier is de wending. Houd er rekening mee dat deze methode geen nieuw
ArrayList
-object maakt. Het retourneert gewoon een lijstverwijzing naar een bestaandArray
-object (dus na het gebruik van deasList
-methode worden er twee verwijzingen naar een bestaandArray
-object gemaakt) - en dit is de reden. Alle methoden die werken op
List
-object, werken mogelijk nietop dit Array-object met behulp van deList
-referentie. Leuk vinden
de grootte vanArray
is bijvoorbeeld een vaste lengte, daarom kunt u uiteraard geen elementen toevoegen aan of verwijderen uit hetArray
-object met behulp van dezeList
-referentie (zoalslist.add(10)
oflist.remove(10);
. Anders wordt UnsupportedOperationException gegenereerd. - elke wijziging die u aanbrengt met behulp van een lijstverwijzing, wordt weerspiegeld in het bestaande
Array
-object (omdat u op een bestaand Array-object werkt met behulp van een lijstverwijzing)
In het eerste geval maakt u een nieuw ArrayList
-object (in het tweede geval wordt alleen een verwijzing naar een bestaand Array-object gemaakt, maar geen nieuw ArrayList
object), dus nu zijn er twee verschillende objecten. Een daarvan is het Array
-object en een andere is het ArrayList
-object en er is geen verband tussen beide (dus wijzigingen in het ene object worden niet weerspiegeld/beïnvloed in een ander object ( dat wil zeggen, in geval 2 zijn Array
en ArrayList
twee verschillende objecten)
Geval 1:
Integer [] ia = {1,2,3,4};
System.out.println("Array : "+Arrays.toString(ia));
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); // new ArrayList object is created , no connection between existing Array Object
list1.add(5);
list1.add(6);
list1.remove(0);
list1.remove(0);
System.out.println("list1: " + list1);
System.out.println("Array: " + Arrays.toString(ia));
Geval 2:
Integer [] ia = {1,2,3,4};
System.out.println("Array: " + Arrays.toString(ia));
List<Integer> list2 = Arrays.asList(ia); // Creates only a (new) List reference to the existing Array object (and NOT a new ArrayList Object)
// list2.add(5); // It will throw java.lang.UnsupportedOperationException - invalid operation (as Array size is fixed)
list2.set(0,10); // Making changes in the existing Array object using the List reference - valid
list2.set(1,11);
ia[2]=12; // Making changes in the existing Array object using the Array reference - valid
System.out.println("list2: " + list2);
System.out.println("Array: " + Arrays.toString(ia));
Antwoord 7
Veel mensen hebben de mechanische details al beantwoord, maar het is vermeldenswaard:
Dit is een slechte ontwerpkeuze van Java.
Java’s asList
methode is gedocumenteerd als “Retourneert een vaste-groottelijst…”. Als je het resultaat neemt en (zeg) de methode .add
aanroept, wordt een UnsupportedOperationException
gegenereerd. Dit is niet-intuïtief gedrag! Als een methode zegt dat het een List
retourneert, is de standaard verwachting dat het een object retourneert dat de methoden van interface List
ondersteunt. Een ontwikkelaar zou niet moeten onthouden welkevan de talloze util.List
-methoden List
s maken die niet alle List
methoden.
Als ze de methode asImmutableList
hadden genoemd, zou het logisch zijn. Of als ze de methode gewoon een echte List
hadden laten retourneren (en de backing-array kopiëren), zou het logisch zijn. Ze besloten de voorkeur te geven aan zowel runtime-performance enkorte namen, ten koste van het schenden van zowel de het principe van de minste verbazingen de goede objectgeoriënteerde praktijk van het vermijden van UnsupportedOperationException
s.
(De ontwerpers hebben mogelijk ook een interface ImmutableList
gemaakt om een overvloed aan UnsupportedOperationException
s te vermijden.)
Antwoord 8
Merk op dat in Java 8 ‘ia’ hierboven Integer[] moet zijn en niet int[]. Arrays.asList() van een int-array retourneert een lijst met een enkel element. Bij gebruik van het codefragment van de OP, zal de compiler het probleem opvangen, maar sommige methoden (bijv. Collections.shuffle()) zullen stilletjes niet doen wat je verwacht.
Antwoord 9
package com.copy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class CopyArray {
public static void main(String[] args) {
List<Integer> list1, list2 = null;
Integer[] intarr = { 3, 4, 2, 1 };
list1 = new ArrayList<Integer>(Arrays.asList(intarr));
list1.add(30);
list2 = Arrays.asList(intarr);
// list2.add(40); Here, we can't modify the existing list,because it's a wrapper
System.out.println("List1");
Iterator<Integer> itr1 = list1.iterator();
while (itr1.hasNext()) {
System.out.println(itr1.next());
}
System.out.println("List2");
Iterator<Integer> itr2 = list2.iterator();
while (itr2.hasNext()) {
System.out.println(itr2.next());
}
}
}
Antwoord 10
Arrays.asList()
Deze methode retourneert zijn eigen implementatie van List. Het neemt een array als argument en bouwt er methoden en attributen bovenop, aangezien het geen gegevens uit een array kopieert maar de originele array gebruikt, veroorzaakt dit een wijziging in de originele array wanneer je de lijst wijzigt die wordt geretourneerd door de Arrays.asList()
methode.
Aan de andere kant, ArrayList(Arrays.asList());
is een constructor van de klasse ArrayList
die een lijst als argument neemt en een ArrayList
retourneert die onafhankelijk is van lijst, dwz Arrays.asList()
in dit geval doorgegeven als argument.
Daarom zie je deze resultaten.
Antwoord 11
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy
2.List<Integer> list2 = Arrays.asList(ia);
In regel 2, Arrays.asList(ia)
retourneert een List
referentie van innerlijke klasse-object gedefinieerd in Arrays
, die ook wel wordt genoemd ArrayList
maar is privé en breidt alleen AbstractList
toe. Dit betekent wat geretourneerd is van Arrays.asList(ia)
is een klasse-object anders dan wat u krijgt van new ArrayList<Integer>
.
U kunt sommige bewerkingen niet gebruiken op regel 2 omdat de innerlijke privéklasse binnen Arrays
geen dergelijke methoden verleent.
Bekijk deze link en zie wat u kunt doen met de privé-innerlijke klasse:
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/arrays.java#arrays.arrayclist
Lijn 1 Maakt een nieuwe ArrayList
Object Kopiëren van elementen uit wat u van lijn 2. kunt krijgen, zodat u kunt doen wat u maar wilt sinds java.util.ArrayList
Biedt al die methoden.
Antwoord 12
Als reactie op sommige opmerkingen die vragen stellen over het gedrag van arrays.aslist () sinds Java 8:
int[] arr1 = {1,2,3};
/*
Arrays are objects in Java, internally int[] will be represented by
an Integer Array object which when printed on console shall output
a pattern such as
[I@address for 1-dim int array,
[[I@address for 2-dim int array,
[[F@address for 2-dim float array etc.
*/
System.out.println(Arrays.asList(arr1));
/*
The line below results in Compile time error as Arrays.asList(int[] array)
returns List<int[]>. The returned list contains only one element
and that is the int[] {1,2,3}
*/
// List<Integer> list1 = Arrays.asList(arr1);
/*
Arrays.asList(arr1) is Arrays$ArrayList object whose only element is int[] array
so the line below prints [[I@...], where [I@... is the array object.
*/
System.out.println(Arrays.asList(arr1));
/*
This prints [I@..., the actual array object stored as single element
in the Arrays$ArrayList object.
*/
System.out.println(Arrays.asList(arr1).get(0));
// prints the contents of array [1,2,3]
System.out.println(Arrays.toString(Arrays.asList(arr1).get(0)));
Integer[] arr2 = {1,2,3};
/*
Arrays.asList(arr) is Arrays$ArrayList object which is
a wrapper list object containing three elements 1,2,3.
Technically, it is pointing to the original Integer[] array
*/
List<Integer> list2 = Arrays.asList(arr2);
// prints the contents of list [1,2,3]
System.out.println(list2);
Antwoord 13
Samenvatting van het verschil –
Als een lijst wordt gemaakt zonder de newte gebruiken, retourneert de operator Arrays.asList()-methode een wrapper, wat betekent:
-
u kunt een bewerking voor toevoegen/bijwerken uitvoeren.
-
de wijzigingen die in de originele array zijn aangebracht, worden ook weergegeven in Lijst en omgekeerd.