web-dev-qa-db-de.com

Unterschied zwischen Arrays.asList (Array) und neuer ArrayList <Integer> (Arrays.asList (Array))

Was ist der Unterschied zwischen 

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

dabei ist ia ein Array von Ganzzahlen.

Ich habe erfahren, dass einige Operationen in list2 nicht erlaubt sind. Warum ist es so? Wie wird es im Speicher abgelegt (Referenzen/Kopie)?

Wenn ich die Listen neu mische, hat list1 keinen Einfluss auf das ursprüngliche Array, aber list2. Dennoch ist list2 etwas verwirrend. 

Wie ArrayList in die Liste aufgenommen wird, unterscheidet sich vom Erstellen neuer ArrayList

list1 differs from (1)
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
86
Dineshkumar
  1. Lassen Sie uns zuerst sehen, was dies bewirkt:

    Arrays.asList(ia)
    

    Es nimmt ein Array ia und erstellt einen Wrapper, der List<Integer> implementiert, wodurch das ursprüngliche Array als Liste verfügbar wird. Es wird nichts kopiert und nur ein einziges Wrapper-Objekt wird erstellt. Operationen auf dem Listenwrapper werden an das ursprüngliche Array weitergegeben. Das bedeutet, wenn Sie den Listen-Wrapper mischen, wird auch das ursprüngliche Array gemischt. Wenn Sie ein Element überschreiben, wird es im ursprünglichen Array überschrieben. Natürlich sind einige List-Operationen auf dem Wrapper nicht zulässig Wenn Sie Elemente aus der Liste entfernen, können Sie die Elemente nur lesen oder überschreiben.

    Beachten Sie, dass der Listen-Wrapper ArrayList nicht erweitert - es handelt sich um eine andere Art von Objekt. ArrayLists besitzen ein eigenes, internes Array, in dem sie ihre Elemente speichern, und können die Größe der internen Arrays usw. ändern. Der Wrapper hat kein eigenes internes Array, er gibt nur Operationen an das ihm gegebene Array weiter.

  2. Andererseits, wenn Sie später ein neues Array erstellen 

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

    dann erstellen Sie ein neues ArrayList, bei dem es sich um eine vollständige, unabhängige Kopie des Originals handelt. Obwohl Sie hier den Wrapper auch mit Arrays.asList erstellen, wird er nur während des Erstellens des neuen ArrayList verwendet und anschließend im Müll gesammelt. Die Struktur dieses neuen ArrayList ist völlig unabhängig vom ursprünglichen Array. Es enthält die gleichen Elemente (sowohl das ursprüngliche Array als auch dieses neue ArrayList-Objekt verweisen auf dieselben Ganzzahlen im Speicher), erstellt jedoch ein neues internes Array, das die Referenzen enthält. Wenn Sie es also mischen, hinzufügen, Elemente usw. entfernen, bleibt das ursprüngliche Array unverändert.

182
Petr Pudlák

Das liegt daran, dass ArrayList, das aus Arrays.asList() resultiert, nicht vom Typ Java.util.ArrayList ist. Arrays.asList() erstellt eine ArrayList vom Typ Java.util.Arrays$ArrayList, die nicht Java.util.ArrayList, sondern nur Java.util.AbstractList erweitert.

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

In diesem Fall ist list1 vom Typ ArrayList.

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

Hier wird die Liste als List-Ansicht zurückgegeben, dh es sind nur die Methoden an diese Schnittstelle angehängt. Daher sind einige Methoden für list2 nicht zulässig.

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

Hier erstellen Sie eine neue ArrayList. Sie übergeben ihm einfach einen Wert im Konstruktor. Dies ist kein Beispiel für Casting. Im Casting könnte es eher so aussehen:

ArrayList list1 = (ArrayList)Arrays.asList(ia);
8
christopher

Ich bin ziemlich spät dran, sowieso wäre eine Erklärung mit Doc-Referenzen für jemanden, der nach einer Antwort sucht, besser.

  1. Java.util.Arrays
  • Dies ist eine Dienstprogrammklasse mit einer Reihe statischer Methoden, die für ein bestimmtes Array verwendet werden
  • asList ist eine solche statische Methode, die das Eingabe-Array verwendet und ein Objekt von Java.util.Arrays.ArrayList zurückgibt, einer statischen verschachtelten Klasse, die die AbstractList erweitert, wodurch die List-Schnittstelle implementiert wird.
  • Arrays.asList (inarray) gibt also einen List-Wrapper um das Eingabe-Array zurück. Dieser Wrapper ist jedoch Java.util.Arrays.ArrayList und nicht Java.util.ArrayList. Er verweist auf dasselbe Array, sodass mehr Elemente zu List hinzugefügt werden Das umwickelte Array würde auch das ursprüngliche Signal beeinflussen, und wir können die Länge nicht ändern.
  1. Java.util.ArrayList
  • ArrayList enthält eine Reihe überladener Konstruktoren

    public ArrayList () - // gibt die Arrayliste mit der Standardkapazität 10 zurück

    public ArrayList (Sammlung c)

    public ArrayList (int initialCapacity)

  • Wenn wir also das von Arrays.asList zurückgegebene Objekt, dh List (AbstractList), an den zweiten Konstruktor weitergeben, wird ein neues dynamisches Array erstellt (diese Arraygröße nimmt zu, wenn wir mehr Elemente als deren Kapazität hinzufügen und auch die neuen Elemente das orignal-Array nicht beeinflussen ) flaches Kopieren des ursprünglichen Arrays ( flaches Kopieren bedeutet, dass nur die Referenzen kopiert werden und keine neuen Objekte der gleichen Objekte wie im ursprünglichen Array erstellt werden.)

3
John Frusciante

Beachten Sie, dass in Java 8 "ia" oben Integer [] und nicht Int [] sein muss. Arrays.asList () eines int-Arrays gibt eine Liste mit einem einzelnen Element zurück. Wenn Sie das Code-Snippet von OP verwenden, wird der Compiler das Problem erkennen, einige Methoden (z. B. Collections.shuffle ()) werden jedoch nicht das tun, was Sie erwarten.

2
Carl Burke
String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.List<String> namesList = Arrays.asList(names);

oder

String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.List<String> temp = Arrays.asList(names);         

Above Statement fügt den Wrapper im Eingabearray hinzu. Daher sind die Methoden wie Hinzufügen und Entfernen nicht auf das Listenreferenzobjekt 'namesList' anwendbar.

Wenn Sie versuchen, ein Element in das vorhandene Array/die Liste einzufügen, erhalten Sie "Exception in thread" main "Java.lang.UnsupportedOperationException".

Die obige Operation kann nur gelesen oder angezeigt werden. 
Das Listenobjekt ..__ kann nicht hinzugefügt oder entfernt werden

String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.ArrayList<String> list1 = new ArrayList<>(Arrays.asList(names));

oder

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 der obigen Anweisung haben Sie eine konkrete Instanz einer ArrayList-Klasse erstellt und eine Liste als Parameter übergeben.

In diesem Fall funktioniert die Methode add & remove ordnungsgemäß, da beide Methoden aus der ArrayList-Klasse stammen. Daher erhalten wir hier keine UnSupportedOperationException.
Änderungen, die im Arraylist-Objekt vorgenommen wurden (Methode zum Hinzufügen oder Entfernen eines Elements in/aus einer Arrayliste), werden im ursprünglichen Java.util.List-Objekt nicht übernommen.

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
2
Avinash Pande

Arrays-Klasse ist vor allem eine Utility-Klasse, die no enthält. von Utility-Methoden für Arrays (dank Arrays-Klasse, sonst hätten wir eigene Methoden für Array-Objekte erstellen müssen)

asList () Methode:

  1. Die asList-Methode ist eine der Utility-Methoden der Array-Klasse. Daher handelt es sich um eine statische Methode, weshalb wir diese Methode über ihren Klassennamen (wie Arrays.asList(T...a)) aufrufen können.
  2. Hier ist die Wendung. Bitte beachten Sie, dass diese Methode kein neues ArrayList-Objekt erstellt. Es wird lediglich eine Listenreferenz auf das vorhandene Array-Objekt zurückgegeben. Nach der asList-Methode werden nun zwei Verweise auf das vorhandene Array-Objekt erstellt.
  3. dies ist der Grund, weshalb alle Methoden, die mit dem List-Objekt arbeiten, NICHT mit diesem List-Verweis wie ___ funktionieren können. Beispielsweise ist die Arrays-Größe fest, daher können Sie offensichtlich keine Elemente zum Array-Objekt hinzufügen oder daraus entfernen mit dieser List-Referenz (wie list.add(10) oder list.remove(10);, sonst wird UnsupportedOperationException ausgelöst)
  4. jede Änderung, die Sie mit Hilfe der Listenreferenz vornehmen, wird durch das Beenden des Arrays-Objekts angezeigt (wenn Sie ein vorhandenes Array-Objekt mithilfe der Listenreferenz bearbeiten).

Im ersten Fall erstellen Sie ein neues Arraylist-Objekt (im zweiten Fall wird nur ein Verweis auf ein vorhandenes Array-Objekt erstellt, jedoch kein neues ArrayList-Objekt). Es gibt also zwei verschiedene Objekte, nämlich Array-Objekt und ein anderes ArrayList-Objekt und keine Verbindung zwischen diesen Objekten sie (also werden Änderungen an einem Objekt nicht in einem anderen Objekt reflektiert/beeinflusst (das ist der Fall, wenn 2 Array und Arraylist zwei verschiedene Objekte sind)

fall 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));

fall 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 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 existing Array object using List reference - valid 
list2.set(1,11); 
ia[2]=12;     // making changes in existing Array object using Array reference - valid
System.out.println("list2 : "+list2);
System.out.println("Array : "+Arrays.toString(ia));
2
qaautodev

Arrays.asList()

diese Methode gibt eine eigene Implementierung von List zurück. Sie verwendet ein Array als Argument und erstellt darauf Methoden und Attribute, da sie keine Daten aus einem Array kopiert, sondern das ursprüngliche Array verwendet. Dies führt zu Änderungen im ursprünglichen Array, wenn Sie Änderungen vornehmen Liste, die von der Arrays.asList() -Methode zurückgegeben wird.

auf der anderen Seite.
ArrayList(Arrays.asList()); ist ein Konstruktor der Klasse ArrayList, der eine Liste als Argument verwendet und eine von der Liste unabhängige ArrayList zurückgibt, d. h. Arrays.asList() wurde in diesem Fall als Argument übergeben. Aus diesem Grund sehen Sie diese Ergebnisse.

1

Viele Leute haben bereits auf die mechanischen Details geantwortet, aber es ist erwähnenswert: Dies ist eine schlechte Entwurfsentscheidung von Java.

Javas asList-Methode ist dokumentiert als "Gibt eine fixed-size -Liste ..." zurück. Wenn Sie das Ergebnis nehmen und die .add-Methode aufrufen, wird eine UnsupportedOperationException ausgegeben. Dies ist ein nicht intuitives Verhalten! Wenn eine Methode angibt, dass sie eine List zurückgibt, wird standardmäßig erwartet, dass ein Objekt zurückgegeben wird, das die Methoden der Schnittstelle List unterstützt. Ein Entwickler sollte sich nicht merken müssen, welche der umpteen util.List-Methoden Lists erstellen, die nicht alle List-Methoden unterstützen.

Wenn sie die Methode asImmutableList genannt hätten, wäre das sinnvoll. Wenn die Methode nur eine tatsächliche List zurückgeben würde (und das Hintergrundarray kopieren würde), wäre dies sinnvoll. Sie beschlossen, sowohl die Laufzeit-Performance als auch Kurznamen zu bevorzugen, und zwar auf Kosten der Verletzung sowohl des Prinzips der wenigsten Überraschung als auch des guten O.O. Praxis, UnsupportedOperationExceptions zu vermeiden.

(Außerdem haben die Designer möglicherweise einen interface ImmutableList erstellt, um eine Fülle von UnsupportedOperationExceptions zu vermeiden.)

1
not-just-yeti
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());
        }
    }
}
1
VicXj

Zusammenfassung des Unterschieds -

wenn die Liste ohne den neuen Operator Arrays.asList () erstellt wird, wird Wrapper zurückgegeben 

1. Sie können einen Vorgang zum Hinzufügen/Aktualisieren durchführen.

2. Die Änderungen, die im ursprünglichen Array vorgenommen wurden, werden auch in der Liste angezeigt und umgekehrt.

0
Raj

Als Antwort auf einige Kommentare, die Fragen zum Verhalten von Arrays.asList () seit Java 8 stellen:

    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);
0
NINCOMPOOP
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
2.List<Integer> list2 = Arrays.asList(ia);

In Zeile 2 gibt Arrays.asList(ia) eine List-Referenz des inneren Klassenobjekts zurück, das in Arrays definiert ist. Dies wird auch als ArrayList bezeichnet, ist jedoch privat und erweitert nur AbstractList. Dies bedeutet, dass das von Arrays.asList(ia) zurückgegebene Klassenobjekt anders ist als das, was Sie von new ArrayList<Integer> erhalten.

Sie können einige Operationen nicht für Zeile 2 verwenden, da die innere private Klasse in Arrays diese Methoden nicht bereitstellt.

Schauen Sie sich diesen Link an und sehen Sie, was Sie mit der privaten inneren Klasse tun können: http://grepcode.com/file/repository.grepcode.com/Java/root/jdk/openjdk/6-b14 /Java/util/Arrays.Java#Arrays.ArrayList

Zeile 1 erstellt ein neues ArrayList-Objekt, das Elemente aus der Zeile 2 kopiert. Sie können also tun, was Sie möchten, da Java.util.ArrayList all diese Methoden zur Verfügung stellt.

0
zek_w