Konvertieren einer Sammlung in ArrayList in Java

1. Übersicht

Das Konvertieren von Java-Sammlungen von einem Typ in einen anderen ist eine häufige Programmieraufgabe. In diesem Tutorial konvertieren wir jede Art von Sammlung in eine ArrayList .

Während des gesamten Tutorials gehen wir davon aus, dass wir bereits eine Sammlung von Foo- Objekten haben. Von dort aus erstellen wir eine ArrayList mit verschiedenen Ansätzen.

2. Unser Beispiel definieren

Aber bevor wir fortfahren, modellieren wir unsere Eingabe und Ausgabe.

Unsere Quelle kann jede Art von Sammlung sein, daher deklarieren wir sie über die Sammlungsoberfläche :

Collection srcCollection; 

Wir müssen eine ArrayList mit demselben Elementtyp erstellen :

ArrayList newList;

3. Verwenden des ArrayList-Konstruktors

Der einfachste Weg, eine Sammlung in eine neue Sammlung zu kopieren, ist die Verwendung ihres Konstruktors.

In unserem vorherigen Handbuch zu ArrayList haben wir erfahren, dass der ArrayList- Konstruktor einen Auflistungsparameter akzeptieren kann:

ArrayList newList = new ArrayList(srcCollection);
  • Die neue ArrayList enthält eine flache Kopie der Foo-Elemente in der Quellensammlung.
  • Die Reihenfolge ist dieselbe wie in der Quellensammlung.

Die Einfachheit des Konstruktors macht ihn in den meisten Szenarien zu einer großartigen Option.

4. Verwenden der Streams-API

Nun wollen wir nutzen die Streams API eine Arraylist aus einer bestehenden Sammlung zu erstellen :

ArrayList newList = srcCollection.stream().collect(toCollection(ArrayList::new));

In diesem Ausschnitt:

  • Wir nehmen den Stream aus der Quellensammlung und wenden den Operator collect () an, um eine Liste zu erstellen
  • Wir geben ArrayList :: new an, um den gewünschten Listentyp zu erhalten
  • Dieser Code erzeugt auch eine flache Kopie.

Wenn wir uns nicht um den genauen Listentyp kümmern würden , könnten wir Folgendes vereinfachen:

List newList = srcCollection.stream().collect(toList());

Beachten Sie, dass toCollection () und toList () statisch aus Collectors importiert werden . Weitere Informationen finden Sie in unserem Handbuch zu Java 8 Collectors.

5. Deep Copy

Vorher haben wir "flache Kopien" erwähnt. Damit meinen wir, dass die Elemente in der neuen Liste genau dieselben Foo- Instanzen sind , die noch in der Quellensammlung vorhanden sind. Aus diesem Grund haben wir die Foo s als Referenz in die newList kopiert .

Wenn wir den Inhalt einer Foo- Instanz in einer der Sammlungen ändern , wird diese Änderung in beiden Sammlungen berücksichtigt . Wenn wir also die Elemente in einer der beiden Sammlungen ändern möchten, ohne die andere zu ändern, müssen wir eine „tiefe Kopie“ durchführen.

Um ein Foo tief zu kopieren , erstellen wir für jedes Element eine völlig neue Foo- Instanz . Folglich müssen alle Foo- Felder in die neuen Instanzen kopiert werden.

Definieren wir unsere Foo- Klasse so, dass sie weiß, wie sie sich selbst tief kopiert:

public class Foo { private int id; private String name; private Foo parent; public Foo(int id, String name, Foo parent) { this.id = id; this.name = name; this.parent = parent; } public Foo deepCopy() { return new Foo( this.id, this.name, this.parent != null ? this.parent.deepCopy() : null); } }

Hier können wir die Felder sehen ID und Name sind int und String . Diese Datentypen werden nach Wert kopiert. Daher können wir einfach beide zuweisen.

Das übergeordnete Feld ist ein weiteres Foo , das eine Klasse ist. Wenn Foo mutiert würde, wäre jeder Code, der diese Referenz teilt, von diesen Änderungen betroffen. Wir müssen das übergeordnete Feld tief kopieren .

Jetzt können wir zu unserer ArrayList- Konvertierung zurückkehren. Wir brauchen nur den Kartenoperator , um die tiefe Kopie in den Flow einzufügen :

ArrayList newList = srcCollection.stream() .map(foo -> foo.deepCopy()) .collect(toCollection(ArrayList::new));

Wir können den Inhalt einer Sammlung ändern, ohne die andere zu beeinflussen.

Eine tiefe Kopie kann abhängig von der Anzahl der Elemente und der Tiefe der Daten ein langwieriger Prozess sein. Die Verwendung eines parallelen Streams kann bei Bedarf zu einer Leistungssteigerung führen.

6. Steuern der Listenreihenfolge

Standardmäßig liefert unser Stream Elemente in derselben Reihenfolge an unsere ArrayList, in der sie in der Quellensammlung vorkommen.

Wenn wir diese Reihenfolge ändern möchten, können wir den sortierten () Operator auf den Stream anwenden . So sortieren Sie unsere Foo- Objekte nach Namen:

ArrayList newList = srcCollection.stream() .sorted(Comparator.comparing(Foo::getName)) .collect(toCollection(ArrayList::new));

Weitere Details zur Stream-Bestellung finden Sie in diesem früheren Tutorial.

7. Fazit

Der ArrayList- Konstruktor ist eine effektive Methode, um den Inhalt einer Sammlung in eine neue ArrayList zu übertragen .

However, if we need to tweak the resulting list, the Streams API provides a powerful way to modify the process.

The code used in this article can be found in its entirety over on GitHub.