Kopiera en lista till en annan lista i Java

1. Översikt

I den här snabbhandledningen visar vi olika sätt att kopiera en lista till en annan lista och ett vanligt fel som produceras i processen.

För en introduktion till användningen av samlingar , se den här artikeln här.

2. Konstruktör

Ett enkelt sätt att kopiera en lista är att använda konstruktören som tar en samling som argument:

List copy = new ArrayList(list);

På grund av det faktum att vi kopierar referens här och inte klonar objekten kommer alla ändringar som görs i ett element att påverka båda listorna.

Av den anledningen är det bra att använda konstruktören för att kopiera oföränderliga objekt:

List copy = new ArrayList(list);

Heltal är en oföränderlig klass, dess värde ställs in när förekomsten skapas och kan aldrig förändras.

En heltal- referens kan således delas av flera listor och trådar och det finns inget sätt att någon kan ändra dess värde.

3. Lista ConcurrentAccessException

Ett vanligt problem med att arbeta med listor är ConcurrentAccessException . Detta kan innebära att vi ändrar listan medan vi försöker kopiera den, troligen i en annan tråd.

För att åtgärda problemet måste vi antingen:

  • Använd en designad för samlad åtkomstsamling
  • Lås samlingen på lämpligt sätt för att itera över den
  • Hitta ett sätt att undvika att behöva kopiera originalsamlingen

Med tanke på vårt senaste tillvägagångssätt är det inte trådsäkert. Så att om vi vill lösa vårt problem med det första alternativet kanske vi vill använda CopyOnWriteArrayList , där alla mutativa operationer implementeras genom att göra en ny kopia av den underliggande matrisen.

Mer information finns i den här artikeln.

Om vi ​​vill låsa samlingen är det möjligt att använda ett primitivt lås för att serieisera läs- / skrivåtkomst, till exempel ReentrantReadWriteLock .

4. Lägg till alla

Ett annat tillvägagångssätt för att kopiera element använder addAll- metoden:

List copy = new ArrayList(); copy.addAll(list);

Det är viktigt att komma ihåg när du använder den här metoden att, som med konstruktören, kommer innehållet i båda listorna att referera till samma objekt.

5. Collections.copy

Den Samlingar klassen består uteslutande av statiska metoder som verkar på eller retur samlingar.

En av dem är kopia , som behöver en källista och en destinationslista minst så länge som källan.

Det bibehåller indexet för varje kopierat element i mållistan, till exempel originalet:

List source = Arrays.asList(1,2,3); List dest = Arrays.asList(4,5,6); Collections.copy(dest, source);

I exemplet ovan har alla tidigare element i destlistan skrivits över eftersom båda listorna har samma storlek.

Om mållistans storlek är större än källan:

List source = Arrays.asList(1, 2, 3); List dest = Arrays.asList(5, 6, 7, 8, 9, 10); Collections.copy(dest, source);

Bara de tre första artiklarna skrivs över medan resten av elementen i listan är bevarade.

6. Använda Java 8

Denna version av Java öppnar våra möjligheter genom att lägga till nya verktyg. Den vi kommer att utforska i nästa exempel är Stream :

List copy = list.stream() .collect(Collectors.toList());

De största fördelarna med detta sätt är möjligheten att använda skip och filter. I nästa exempel ska vi hoppa över det första elementet:

List copy = list.stream() .skip(1) .collect(Collectors.toList());

Det är också möjligt att filtrera efter strängens längd eller genom att jämföra ett attribut för våra objekt:

List copy = list.stream() .filter(s -> s.length() > 10) .collect(Collectors.toList());
List flowers = list.stream() .filter(f -> f.getPetals() > 6) .collect(Collectors.toList());

Det är troligt att vi vill arbeta på ett nollsäkert sätt:

List flowers = Optional.ofNullable(list) .map(List::stream)   .orElseGet(Stream::empty)   .collect(Collectors.toList());

Och hoppa över ett element på detta sätt också:

List flowers = Optional.ofNullable(list)   .map(List::stream).orElseGet(Stream::empty)   .skip(1)   .collect(Collectors.toList());

7. Använda Java 10

Slutligen tillåter en av de senaste Java-versionerna oss att skapa en oföränderlig lista som innehåller elementen i den givna samlingen:

List copy = List.copyOf(list);
De enda villkoren är att den givna samlingen inte får vara null och att den inte får innehålla några nullelement.

8. Slutsats

I den här artikeln har vi undersökt olika sätt att kopiera en lista till en annan lista med olika Java- versioner och ett vanligt fel som produceras under processen. Som alltid kan kodprover hittas på GitHub här och här.