Verschil tussen Arrays.asList(array) en nieuwe ArrayList<Integer>(Arrays.asList(array))

Wat is het verschil tussen

  • List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); // Copy

  • List<Integer> list2 = Arrays.asList(ia);

, waarbij iaeen 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 list1geen invloed op de originele array, maar list2wel. Maar toch is list2enigszins verwarrend.

Hoe verschilt het opwaarderen van een ArrayListnaar 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%

  1. Laten we eerst eens kijken wat dit doet:

    Arrays.asList(ia)
    

    Er is een array iavoor nodig en er wordt een wrapper gemaakt die List<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 sommige List-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 ArrayListniet uitbreidt – het is een ander soort object. ArrayLists 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.

  2. Aan de andere kant, als u vervolgens een nieuwe array maakt als

    new ArrayList<Integer>(Arrays.asList(ia))
    

    vervolgens maakt u een nieuwe ArrayListaan, die een volledige, onafhankelijke kopie is van de originele. Hoewel u hier de wrapper ook maakt met behulp van Arrays.asList, wordt deze alleen gebruikt tijdens de constructie van de nieuwe ArrayListen wordt deze daarna als afval verzameld. De structuur van deze nieuwe ArrayListis volledig onafhankelijk van de originele array. Het bevat dezelfde elementen (zowel de originele array als deze nieuwe ArrayListverwijzen 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 ArrayListresulterend uit Arrays.asList()niet van het type java.util.ArrayListis.

Arrays.asList()maakt een ArrayListvan het type java.util.Arrays$ArrayListdie java.util.ArrayList, maar breidt alleen java.util.AbstractListuit.


Antwoord 3, autoriteit 4%

List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy

In dit geval, list1is van het type ArrayList.

List<Integer> list2 = Arrays.asList(ia);

Hier wordt de lijst geretourneerd als een ListWeergave, 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 ArrayListmaken. 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
  • te werken

  • 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.

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

  1. asListis een van de hulpprogramma’s van de klasse Array, het is een statische methode en daarom kunnen we deze methode bij de klassenaam aanroepen (zoals Arrays.asList(T...a))
  2. Hier is de wending. Houd er rekening mee dat deze methode geen nieuw ArrayList-object maakt. Het retourneert gewoon een lijstverwijzing naar een bestaand Array-object (dus na het gebruik van de asList-methode worden er twee verwijzingen naar een bestaand Array-object gemaakt)
  3. en dit is de reden. Alle methoden die werken op List-object, werken mogelijk nietop dit Array-object met behulp van de List-referentie. Leuk vinden
    de grootte van Arrayis bijvoorbeeld een vaste lengte, daarom kunt u uiteraard geen elementen toevoegen aan of verwijderen uit het Array-object met behulp van deze List-referentie (zoals list.add(10)of list.remove(10);. Anders wordt UnsupportedOperationException gegenereerd.
  4. 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 ArrayListobject), 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 Arrayen ArrayListtwee 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 asListmethode is gedocumenteerd als “Retourneert een vaste-groottelijst…”. Als je het resultaat neemt en (zeg) de methode .addaanroept, wordt een UnsupportedOperationExceptiongegenereerd. Dit is niet-intuïtief gedrag! Als een methode zegt dat het een Listretourneert, is de standaard verwachting dat het een object retourneert dat de methoden van interface Listondersteunt. Een ontwikkelaar zou niet moeten onthouden welkevan de talloze util.List-methoden Lists maken die niet alle Listmethoden.

Als ze de methode asImmutableListhadden genoemd, zou het logisch zijn. Of als ze de methode gewoon een echte Listhadden 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 UnsupportedOperationExceptions.

(De ontwerpers hebben mogelijk ook een interface ImmutableListgemaakt om een overvloed aan UnsupportedOperationExceptions 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 ArrayListdie een lijst als argument neemt en een ArrayListretourneert 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 Listreferentie van innerlijke klasse-object gedefinieerd in Arrays, die ook wel wordt genoemd ArrayListmaar is privé en breidt alleen AbstractListtoe. 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 Arraysgeen 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 ArrayListObject Kopiëren van elementen uit wat u van lijn 2. kunt krijgen, zodat u kunt doen wat u maar wilt sinds java.util.ArrayListBiedt 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 
       [[email protected] for 1-dim int array,
       [[[email protected] for 2-dim int array, 
       [[[email protected] 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 [[[email protected]], where [[email protected] is the array object.
    */
    System.out.println(Arrays.asList(arr1)); 
    /* 
     This prints [[email protected], 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:

  1. u kunt een bewerking voor toevoegen/bijwerken uitvoeren.

  2. de wijzigingen die in de originele array zijn aangebracht, worden ook weergegeven in Lijst en omgekeerd.

Other episodes