Een collectie converteren naar ArrayList in Java

1. Overzicht

Het converteren van Java-verzamelingen van het ene type naar het andere is een algemene programmeertaak. In deze zelfstudie converteren we elk type Verzameling aan een ArrayList.

In de hele tutorial gaan we ervan uit dat we al een verzameling Foo voorwerpen. Van daaruit maken we een ArrayList met behulp van verschillende benaderingen.

2. Ons voorbeeld definiëren

Maar laten we, voordat we verder gaan, onze input en output modelleren.

Onze bron kan elk type verzameling zijn, dus we geven het aan met behulp van de Verzameling koppel:

Collectie srcCollection; 

We moeten een ArrayList met hetzelfde elementtype:

ArrayList newList;

3. Met behulp van de ArrayList Constructor

De eenvoudigste manier om een ​​verzameling naar een nieuwe verzameling te kopiëren, is door de constructor ervan te gebruiken.

In onze vorige gids voor ArrayList hebben we geleerd dat de ArrayList constructor kan een verzamelingsparameter accepteren:

ArrayList newList = nieuwe ArrayList (srcCollection);
  • De nieuwe ArrayList bevat een ondiepe kopie van de Foo-elementen in de broncollectie.
  • De volgorde is dezelfde als die in de broncollectie.

De eenvoud van de constructor maakt het in de meeste scenario's een geweldige optie.

4. Met behulp van de Streams API

Nu, laten we profiteren van de Streams API om een ​​ArrayList te maken op basis van een bestaande collectie:

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

In dit fragment:

  • We halen de stream uit de broncollectie en passen de verzamelen() operator om een Lijst
  • We specificeren ArrayList :: nieuw om het gewenste lijsttype te krijgen
  • Deze code zal ook een ondiepe kopie produceren.

Als we ons geen zorgen maakten over het exacte Lijst type, kunnen we vereenvoudigen:

Lijst newList = srcCollection.stream (). Collect (toList ());

Let daar op toCollection () en toList () worden statisch geïmporteerd uit Verzamelaars. Raadpleeg onze gids over Java 8's Collectors voor meer informatie.

5. Diepe kopie

Voordat we het hadden over “ondiepe kopieën”. Daarmee bedoelen we dat de elementen in de nieuwe lijst zijn exact hetzelfde Foo gevallen die nog steeds bestaan ​​in de broncollectie. Daarom hebben we het Foos naar de nieuwe lijst door verwijzing.

Als we de inhoud van een Foo bijvoorbeeld in beide collecties dat wijziging zal in beide collecties worden weerspiegeld. Dus als we de elementen in beide collecties willen wijzigen zonder als we de andere wijzigen, moeten we een 'diepe kopie' uitvoeren.

Om een Foo, wij creëer een volledig nieuw Foo bijvoorbeeld voor elk element. Bijgevolg zijn alle Foo velden moeten naar de nieuwe instanties worden gekopieerd.

Laten we onze definiëren Foo class zodat het weet hoe het zichzelf moet kopiëren:

openbare klasse Foo {privé int id; private String naam; privé Foo-ouder; openbare Foo (int id, String naam, Foo ouder) {this.id = id; this.name = naam; this.parent = ouder; } openbare Foo deepCopy () {retourneer nieuwe Foo (this.id, this.name, this.parent! = null? this.parent.deepCopy (): null); }}

Hier kunnen we de velden zien ID kaart en naam zijn int en Draad. Deze gegevenstypen worden op waarde gekopieerd. Daarom kunnen we ze eenvoudig allebei toewijzen.

De ouder veld is een ander Foo, dat is een klasse. Als Foo gemuteerd is, wordt elke code die die referentie deelt, beïnvloed door deze wijzigingen. We moeten het ouder veld-.

Nu kunnen we teruggaan naar onze ArrayList conversie. We hebben alleen de kaart operator om de diepe kopie in te voegen in de stroom:

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

We kunnen de inhoud van beide collecties wijzigen zonder de andere te beïnvloeden.

Een diepe kopie kan een langdurig proces zijn, afhankelijk van het aantal elementen en de diepte van de gegevens. Het gebruik van een parallelle stream kan indien nodig de prestaties verbeteren.

6. Beheren van de lijstvolgorde

Standaard levert onze stream elementen aan ons ArrayList in dezelfde volgorde als ze worden aangetroffen in de broncollectie.

Als we die volgorde willen wijzigen we zouden de gesorteerd () operator naar de stream. Om onze Foo objecten op naam:

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

We kunnen meer informatie vinden over het bestellen van streams in deze eerdere tutorial.

7. Conclusie

De ArrayList constructor is een effectieve manier om de inhoud van een Verzameling in een nieuw ArrayList.

Als we de resulterende lijst echter moeten aanpassen, biedt de Streams API een krachtige manier om het proces aan te passen.

De code die in dit artikel wordt gebruikt, is in zijn geheel te vinden op GitHub.