Hoe een array in Java te kopiëren

1. Overzicht

In dit korte artikel bespreken we verschillende methoden voor het kopiëren van arrays in Java. Het kopiëren van een array lijkt misschien een triviale taak, maar het kan onverwachte resultaten en programmagedrag veroorzaken als het niet zorgvuldig wordt uitgevoerd.

2. Het Systeem Klasse

Laten we beginnen met de kern-Java-bibliotheek - System.arrayCopy (); dit kopieert een array van een bronarray naar een bestemmingsarray, waarbij de kopieeractie wordt gestart vanaf de bronpositie naar de doelpositie tot de opgegeven lengte.

Het aantal elementen dat naar de doelmatrix wordt gekopieerd, is gelijk aan de opgegeven lengte. Het biedt een gemakkelijke manier om een ​​subreeks van een array naar een andere te kopiëren.

Als een van de array-argumenten nul, het gooit een NullPointerException en als een van de integer-argumenten negatief is of buiten het bereik valt, wordt een gegenereerd IndexOutOfBoundException.

Laten we eens kijken naar een voorbeeld om een ​​volledige array naar een andere te kopiëren met behulp van de java.util.System klasse:

int [] array = {23, 43, 55}; int [] copiedArray = nieuwe int [3]; System.arraycopy (array, 0, copiedArray, 0, 3);

Argumenten voor deze methode zijn; een bronarray, de startpositie om te kopiëren van de bronarray, een bestemmingsarray, de startpositie in de bestemmingsarray en het aantal te kopiëren elementen.

Laten we eens kijken naar een ander voorbeeld dat het kopiëren van een subreeks van een bronarray naar een bestemming laat zien:

int [] array = {23, 43, 55, 12, 65, 88, 92}; int [] copiedArray = nieuwe int [3]; System.arraycopy (array, 2, copiedArray, 0, 3); 
assertTrue (3 == copiedArray.length); assertTrue (copiedArray [0] == array [2]); assertTrue (copiedArray [1] == array [3]); assertTrue (copiedArray [2] == array [4]); 

3. Het Arrays Klasse

De Arrays class biedt ook meerdere overbelaste methoden om een ​​array naar een andere te kopiëren. Intern gebruikt het dezelfde aanpak die wordt geboden door Systeem klasse die we eerder hebben gezien. Het biedt hoofdzakelijk twee methoden, kopie van(…) en copyRangeOf (…).

Laten we eens kijken kopie van eerste:

int [] array = {23, 43, 55, 12}; int newLength = array.length; int [] copiedArray = Arrays.copyOf (array, newLength); 

Het is belangrijk om dat op te merken Arrays klasse gebruikt Math.min (...) voor het selecteren van het minimum van de bronarraylengte en de waarde van de nieuwe lengteparameter om de grootte van de resulterende array te bepalen.

Arrays.copyOfRange () duurt 2 parameters, ‘van' en ‘naar' naast de bronarray-parameter. De resulterende array bevat de ‘van' index maar de 'naar' index is uitgesloten. Laten we een voorbeeld bekijken:

int [] array = {23, 43, 55, 12, 65, 88, 92}; int [] copiedArray = Arrays.copyOfRange (array, 1, 4); 
assertTrue (3 == copiedArray.length); assertTrue (copiedArray [0] == array [1]); assertTrue (copiedArray [1] == array [2]); assertTrue (copiedArray [2] == array [3]);

Beide methoden maak een ondiepe kopie van objecten indien toegepast op een array van niet-primitieve objecttypen. Laten we een voorbeeld van een testcase bekijken:

Werknemer [] copiedArray = Arrays.copyOf (werknemers, werknemers.lengte); werknemers [0] .setName (werknemers [0] .getName () + "_Changed"); assertArrayEquals (copiedArray, array);

Omdat het resultaat een ondiepe kopie is, veroorzaakte een verandering in de naam van de werknemer van een element van de originele array de verandering in de copy-array.

En dus - als we een diepe kopie van niet-primitieve typen willen maken - kunnen we gaan voor de andere opties die in de komende secties worden beschreven.

4. Array kopiëren met Object.clone ()

Object.clone () is geërfd van Voorwerp klasse in een array.

Laten we eerst een reeks primitieve typen kopiëren met behulp van de kloonmethode:

int [] array = {23, 43, 55, 12}; int [] copiedArray = array.clone (); 

En een bewijs dat het werkt:

assertArrayEquals (copiedArray, array); matrix [0] = 9; assertTrue (copiedArray [0]! = array [0]);

Het bovenstaande voorbeeld laat zien dat ze dezelfde inhoud hebben na het klonen, maar ze bevatten verschillende verwijzingen, dus elke wijziging in een van deze heeft geen invloed op de andere.

Aan de andere kant, als we met dezelfde methode een reeks niet-primitieve typen klonen, zullen de resultaten anders zijn.

Het creëert een ondiepe kopie van de niet-primitieve type array-elementen, zelfs als de klasse van het ingesloten object de Te klonen interface en overschrijft de kloon () methode van de Voorwerp klasse.

Laten we een voorbeeld bekijken:

public class Address implementeert Cloneable {// ... @Override protected Object clone () gooit CloneNotSupportedException {super.clone (); Adres adres = nieuw adres (); address.setCity (this.city); retouradres; }} 

We kunnen onze implementatie testen door een nieuwe reeks adressen te maken en onze kloon () methode:

Adres [] adressen = createAddressArray (); Adres [] copiedArray = adressen.clone (); adressen [0] .setCity (adressen [0] .getCity () + "_Changed"); 
assertArrayEquals (copiedArray, adressen);

Dit voorbeeld laat zien dat elke verandering in de originele of gekopieerde array de verandering in de andere zou veroorzaken, zelfs als de omsloten objecten zijn Te klonen.

5. Gebruik de Stroom API

Het blijkt dat we de Stream API ook kunnen gebruiken voor het kopiëren van arrays. Laten we een voorbeeld bekijken:

String [] strArray = {"orange", "red", "green '"}; String [] copiedArray = Arrays.stream (strArray) .toArray (String [] :: nieuw); 

Voor de niet-primitieve typen zal het ook een oppervlakkige kopie van objecten maken. Om meer te weten te komen over Java 8-streams, kunt u hier beginnen.

6. Externe bibliotheken

Apache Commons 3 biedt een hulpprogramma-klasse aan met de naam SerializationUtils dat levert een kloon (...) methode. Het is erg handig als we een diepe kopie moeten maken van een reeks niet-primitieve typen. Het kan vanaf hier worden gedownload en de Maven-afhankelijkheid is:

 org.apache.commons commons-lang3 3.5 

Laten we een testcase bekijken:

openbare klasse Werknemer implementeert Serializable {// velden // standaard getters en setters} Werknemer [] werknemers = createEmployeesArray (); Werknemer [] copiedArray = SerializationUtils.clone (werknemers); 
werknemers [0] .setName (werknemers [0] .getName () + "_Changed"); assertFalse (copiedArray [0] .getName (). is gelijk aan (werknemers [0] .getName ()));

Deze klasse vereist dat elk object de Serialiseerbaar koppel. Qua prestaties is het langzamer dan de kloonmethoden die handmatig zijn geschreven om elk van de objecten in onze objectgrafiek te kopiëren.

7. Conclusie

In deze tutorial hebben we de verschillende opties bekeken om een ​​array in Java te kopiëren.

De te gebruiken methode is voornamelijk afhankelijk van het exacte scenario. Zolang we een primitief type array gebruiken, kunnen we alle methoden gebruiken die worden aangeboden door de Systeem en Arrays klassen. Er mag geen verschil in prestatie zijn.

Voor niet-primitieve typen, als we een diepe kopie van een array moeten maken, kunnen we ofwel de SerializationUtils of expliciet kloonmethoden aan onze klassen toevoegen.

En zoals altijd zijn de voorbeelden in dit artikel beschikbaar op GitHub.


$config[zx-auto] not found$config[zx-overlay] not found