Java >> Java tutorial >  >> Tag >> ArrayList

Konvertering af en samling til ArrayList i Java

1. Oversigt

Konvertering af Java-samlinger fra én type til en anden er en almindelig programmeringsopgave. I dette selvstudie konverterer vi enhver type samling til en ArrayList .

Gennem hele øvelsen antager vi, at vi allerede har en samling af Foo genstande. Derfra opretter vi en ArrayList  ved hjælp af forskellige tilgange.

2. Definer vores eksempel

Men før vi fortsætter, lad os modellere vores input og output.

Vores kilde kan være enhver form for samling, så vi erklærer den ved hjælp af Samlingen grænseflade:

Collection<Foo> srcCollection;

Vi skal lave en ArrayList med samme elementtype:

ArrayList<Foo> newList;

3. Brug af ArrayList Constructor

Den enkleste måde at kopiere en samling til en ny samling på er at bruge dens konstruktør.

I vores tidligere guide til ArrayList lærte vi, at ArrayList konstruktør kan acceptere en samlingsparameter:

ArrayList<Foo> newList = new ArrayList<>(srcCollection);
  • Den nye ArrayList indeholder en overfladisk kopi af Foo-elementerne i kildesamlingen.
  • Rækkefølgen er den samme som en i kildesamlingen.

Konstruktørens enkelhed gør den til en god mulighed i de fleste scenarier.

4. Brug af Streams API

Nu lad os udnytte Streams API til at oprette en ArrayList fra en eksisterende samling :

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

I dette uddrag:

  • Vi tager strømmen fra kildesamlingen og anvender collect() operatør for at oprette en liste
  • Vi specificerer ArrayList::new for at få den listetype, vi ønsker
  • Denne kode vil også producere en overfladisk kopi.

Hvis vi ikke var bekymrede over den nøjagtige liste type, kunne vi forenkle:

List<Foo> newList = srcCollection.stream().collect(toList());

Bemærk, at toCollection() og toList() er statisk importeret fra Collectors . Du kan få flere oplysninger i vores vejledning om Java 8's samlere.

5. Deep Copy

Før nævnte vi "overfladiske kopier". Med det mener vi, at elementerne i den nye liste er nøjagtig de samme Foo forekomster der stadig findes i kildesamlingen. Derfor har vi kopieret Foo s til nyliste ved henvisning.

Hvis vi ændrer indholdet af en Foo forekomst i begge samlinger, atændring vil blive afspejlet i begge samlinger . Derfor, hvis vi ønsker at ændre elementerne i en af ​​samlingerne uden ved at ændre den anden, skal vi udføre en "dyb kopi."

For at dybe kopiere en Foo , vi opretter en helt ny Foo instans for hvert element . Derfor er alle Foo felter skal kopieres til de nye forekomster.

Lad os definere vores Foo klasse, så den ved, hvordan den skal kopiere sig selv:

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

Her kan vi se felterne id og navn er int og streng . Disse datatyper kopieres efter værdi. Derfor kan vi simpelthen tildele dem begge.

forælderen felt er en anden Foo , som er en klasse. Hvis Foo  blev muteret, vil enhver kode, der deler den reference, blive påvirket af disse ændringer. Vi skal dybt kopiere forælderen felt .

Nu kan vi vende tilbage til vores ArrayList konvertering. Vi mangler bare kortet operatør for at indsætte den dybe kopi ind i strømmen:

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

Vi kan ændre indholdet af begge samlinger uden at påvirke den anden.

En dyb kopi kan være en langvarig proces afhængigt af antallet af elementer og dybden af ​​dataene. Brug af en parallel stream her kan give et ydelsesboost, hvis det er nødvendigt.

6. Kontrol af listerækkefølgen

Som standard vil vores stream levere elementer til vores ArrayList i samme rækkefølge, som de stødes på i kildesamlingen.

Hvis vi ønsker at ændre denne rækkefølge kan vi anvende sorted() operatør til strømmen . For at sortere vores Foo objekter efter navn:

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

Vi kan finde yderligere oplysninger om streambestilling i dette tidligere selvstudie.

7. Konklusion

ArrayList constructor er en effektiv måde at få indholdet af en samling på ind i en ny ArrayList .

Men hvis vi har brug for at tilpasse den resulterende liste, giver Streams API en effektiv måde at ændre processen på.

Koden brugt i denne artikel kan findes i sin helhed på GitHub.


Java tag