Ako kopírovať pole v Jave

1. Prehľad

V tomto rýchlom článku si ukážeme rôzne metódy kopírovania polí v prostredí Java. Kópia poľa sa môže javiť ako triviálna úloha, ale ak nebude vykonaná opatrne, môže spôsobiť neočakávané výsledky a správanie programu.

2. The Systém Trieda

Začnime s hlavnou knižnicou Java - System.arrayCopy (); toto skopíruje pole zo zdrojového poľa do cieľového poľa, pričom sa spustí akcia kopírovania zo zdrojovej polohy do cieľovej polohy do určenej dĺžky.

Počet prvkov kopírovaných do cieľového poľa sa rovná zadanej dĺžke. Poskytuje jednoduchý spôsob kopírovania podsekvencie poľa do iného.

Ak je niektorý z argumentov poľa nulový, hodí to NullPointerException a ak je niektorý z celočíselných argumentov záporný alebo je mimo rozsahu, hodí znak IndexOutOfBoundException.

Pozrime sa na príklad kopírovania celého poľa do iného pomocou znaku java.util.System trieda:

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

Argumenty, ktoré táto metóda vyžaduje, sú; zdrojové pole, začiatočná pozícia na kopírovanie zo zdrojového poľa, cieľové pole, východisková pozícia v cieľovom poli a počet prvkov, ktoré sa majú kopírovať.

Pozrime sa na ďalší príklad, ktorý ukazuje kopírovanie podsekvencie zo zdrojového poľa do cieľa:

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

3. The Polia Trieda

The Polia trieda tiež ponúka viac preťažených metód na kopírovanie poľa do iného. Vnútorne používa rovnaký prístup ako Systém triedy, ktorú sme videli už skôr. Poskytuje hlavne dve metódy, kópia(…) a copyRangeOf (…).

Poďme sa na to pozrieť kópia najprv:

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

Je dôležité si to uvedomiť Polia trieda používa Math.min (…) na výber minima dĺžky zdrojového poľa a hodnoty nového parametra dĺžky na určenie veľkosti výsledného poľa.

Arrays.copyOfRange () trvá 2 parametre, ‘z ' a ‘do ' okrem parametra zdrojového poľa. Výsledné pole obsahuje ‘z ' index ale „Do“ index je vylúčený. Pozrime sa na príklad:

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

Obidve tieto metódy urob plytkú kópiu objektov, ak sa použije na pole neprimitívnych typov objektov. Pozrime sa na príklad testovacieho prípadu:

Employee [] copiedArray = Arrays.copyOf (zamestnanci, zamestnanci.dĺžka); zamestnanci [0] .setName (zamestnanci [0] .getName () + "_Zmenené"); assertArrayEquals (copiedArray, pole);

Pretože výsledkom je plytká kópia - zmena v mene zamestnanca prvku pôvodného poľa spôsobila zmenu v poli pre kopírovanie.

A tak - ak chceme urobiť hlbokú kópiu neprimitívnych typov - môžeme ísť na ďalšie možnosti popísané v nasledujúcich častiach.

4. Pole Kopírovať pomocou Object.clone ()

Object.clone () sa dedí z Objekt trieda v poli.

Najprv skopírujme rad primitívnych typov pomocou metódy klonovania:

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

A dôkaz, že to funguje:

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

Vyššie uvedený príklad ukazuje, že majú po klonovaní rovnaký obsah, ale obsahujú rôzne referencie, takže žiadna zmena v žiadnom z nich neovplyvní ten druhý.

Na druhej strane, ak klonujeme pole neprimitívnych typov pomocou rovnakej metódy, výsledky sa budú líšiť.

Vytvára plytká kópia prvkov primitívneho typu poľa, aj keď trieda uzavretého objektu implementuje Cloneable rozhranie a prepíše klon () metóda z Objekt trieda.

Pozrime sa na príklad:

verejná trieda Adresa implementuje Cloneable {// ... @Override chránený objekt clone () hodí CloneNotSupportedException {super.clone (); Adresa adresa = nová adresa (); address.setCity (this.city); spiatočná adresa; }} 

Našu implementáciu môžeme otestovať vytvorením nového radu adries a vyvolaním našej klon () metóda:

Adresa [] adresy = createAddressArray (); Adresa [] copiedArray = addresses.clone (); adresy [0] .setCity (adresy [0] .getCity () + "_Changed"); 
assertArrayEquals (copiedArray, adresy);

Tento príklad ukazuje, že akákoľvek zmena v pôvodnom alebo skopírovanom poli by spôsobila zmenu v tom druhom, aj keď sú uzavreté objekty Cloneable.

5. Pomocou Prúd API

Ukázalo sa, že aj na kopírovanie polí môžeme použiť Stream API. Pozrime sa na príklad:

Reťazec [] strArray = {"oranžová", "červená", "zelená '"}; String [] copiedArray = Arrays.stream (strArray) .toArray (String [] :: nové); 

Pre neprimitívne typy urobí tiež plytkú kópiu objektov. Ak sa chcete dozvedieť viac o Streamy Java 8, môžete začať tu.

6. Externé knižnice

Apache Commons 3 ponúka úžitkovú triedu s názvom SerializationUtils ktorá poskytuje a klonovať (...) metóda. Je to veľmi užitočné, ak potrebujeme urobiť hlbokú kópiu radu neprimitívnych typov. Môžete si ho stiahnuť odtiaľto a jeho závislosť Maven je:

 org.apache.commons commons-lang3 3.5 

Pozrime sa na testovací prípad:

verejná trieda Zamestnanec implementuje Serializovateľné {// polia // štandardné getre a settery} Zamestnanec [] zamestnanci = createEmployeesArray (); Employee [] copiedArray = SerializationUtils.clone (zamestnanci); 
zamestnanci [0] .setName (zamestnanci [0] .getName () + "_Zmenené"); assertFalse (copiedArray [0] .getName (). equals (zamestnanci [0] .getName ()));

Táto trieda vyžaduje, aby každý objekt mal implementovať Serializovateľné rozhranie. Pokiaľ ide o výkon, je to pomalšie ako pri kopírovaní metód klonovania napísaných ručne pre každý z objektov v našom grafe objektov.

7. Záver

V tomto tutoriáli sme sa pozreli na rôzne možnosti kopírovania poľa v Jave.

Spôsob použitia závisí hlavne od presného scenára. Pokiaľ používame pole primitívneho typu, môžeme použiť ktorúkoľvek z metód ponúkaných Systém a Polia triedy. Nemal by byť žiadny rozdiel vo výkone.

Pre non-primitívne typy, ak potrebujeme urobiť hlbokú kópiu poľa, môžeme použiť buď SerializationUtils alebo pridajte do našich tried výslovne klonové metódy.

A ako vždy sú príklady uvedené v tomto článku k dispozícii na stránkach GitHub.


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