Tömb másolása Java-ban

1. Áttekintés

Ebben a rövid cikkben különféle tömbmásolási módszereket tárgyalunk a Java-ban. A tömb példánya triviális feladatnak tűnhet, de ha nem gondosan végezzük, váratlan eredményeket és program viselkedést okozhat.

2. A Rendszer Osztály

Kezdjük a Java alapkönyvtárral - System.arrayCopy (); ez egy tömböt átmásol egy forrás tömbből egy cél tömbbe, kezdve a másolási műveletet a forrás pozíciótól a cél pozícióig a megadott hosszúságig.

A céltömbbe másolt elemek száma megegyezik a megadott hosszúsággal. Könnyű módot kínál egy tömb alsorrendjének másolására egy másikba.

Ha a tömb egyik argumentuma az nulla, dob egy NullPointerException és ha az egész argumentum bármelyike ​​negatív vagy tartományon kívül esik, akkor egy IndexOutOfBoundException.

Nézzünk meg egy példát egy teljes tömb másolására egy másikra a java.util.System osztály:

int [] tömb = {23, 43, 55}; int [] copiedArray = új int [3]; System.arraycopy (tömb, 0, copiedArray, 0, 3);

A módszer érvei a következők; forrás tömb, a forrás tömbből másolandó kiinduló helyzet, cél tömb, a cél tömb kiindulási helye és a másolandó elemek száma.

Vessen egy pillantást egy másik példára, amely egy részsorrend másolását mutatja egy forrás tömbből a célba:

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

3. Az Tömbök Osztály

A Tömbök osztály több túlterhelt módszert is kínál egy tömb másolásához. Belsőleg ugyanazt a megközelítést alkalmazza, amelyet a Rendszer osztály, amelyet korábban láttunk. Főleg két módszert kínál, másolata(…) és copyRangeOf (…).

Nézzük meg másolata első:

int [] tömb = {23, 43, 55, 12}; int newLength = tömb.hossz; int [] copiedArray = Tömbök.copyOf (tömb, newLength); 

Fontos megjegyezni Tömbök osztály használ Math.min (…) a forrás tömbhossz minimumának és az új hosszparaméter értékének kiválasztásához a kapott tömb méretének meghatározásához.

Arrays.copyOfRange () 2 paramétert vesz fel,tól től' és „nak nek' a forrás tömb paraméter mellett. A kapott tömb tartalmazza atól től' index, de a 'nak nek' index kizárt. Lássunk egy példát:

int [] tömb = {23, 43, 55, 12, 65, 88, 92}; int [] copiedArray = Tömbök.copyOfRange (tömb, 1, 4); 
assertTrue (3 == copiedArray.length); assertTrue (copiedArray [0] == tömb [1]); assertTrue (copiedArray [1] == tömb [2]); assertTrue (copiedArray [2] == tömb [3]);

Mindkét módszer sekély példányt készítsen objektumok, ha nem primitív objektumtípusok tömbjére alkalmazzák. Lássunk egy példát a tesztesetre:

Alkalmazott [] copiedArray = Arrays.copyOf (alkalmazottak, alkalmazottak.hossz); alkalmazottak [0] .setName (alkalmazottak [0] .getName () + "_Change"); assertArrayEquals (copiedArray, tömb);

Mivel az eredmény sekély másolat - az eredeti tömb elemének alkalmazott nevében bekövetkezett változás megváltoztatta a másolási tömböt.

Tehát - ha a nem primitív típusok mély másolatát akarjuk elvégezni - a következő szakaszokban leírt további lehetőségek mellett dönthetünk.

4. Array Copy With Object.clone ()

Object.clone () -től öröklődik Tárgy osztály egy tömbben.

Először másoljunk egy primitív tömböt klón módszerrel:

int [] tömb = {23, 43, 55, 12}; int [] copiedArray = tömb.klón (); 

És bizonyíték arra, hogy működik:

assertArrayEquals (copiedArray, tömb); tömb [0] = 9; assertTrue (copiedArray [0]! = tömb [0]);

A fenti példa azt mutatja, hogy a klónozás után ugyanaz a tartalom van, de különböző hivatkozásokkal rendelkeznek, így bármelyikben bekövetkező változás nem érinti a másikat.

Másrészt, ha nem primitív típusú tömböt klónozunk ugyanazon módszerrel, akkor az eredmények eltérőek lesznek.

Teremt sekély példány a nem primitív típusú tömb elemek közül, még akkor is, ha a zárt objektum osztálya végrehajtja a Klónozható interfész és felülírja a klón () módszer a Tárgy osztály.

Nézzünk meg egy példát:

public class Address implementálja a Cloneable {// ... @Orride protected Object clone () dobja a CloneNotSupportedException {super.clone (); Cím címe = új cím (); address.setCity (this.city); visszaszállítási cím; }} 

Tesztelhetjük megvalósításunkat egy új címtömb létrehozásával és a mi meghívásunkkal klón () módszer:

Cím [] címek = createAddressArray (); Cím [] copiedArray = címek.klón (); címek [0] .setCity (címek [0] .getCity () + "_Changed"); 
assertArrayEquals (copiedArray, címek);

Ez a példa azt mutatja, hogy az eredeti vagy a másolt tömb bármilyen változása a másik változását okozhatja akkor is, ha a zárt objektumokat Klónozható.

5. A Folyam API

Kiderült, hogy a Stream API-t is használhatjuk tömbök másolásához. Nézzünk meg egy példát:

Karakterlánc [] strArray = {"narancs", "piros", "zöld" "}; String [] copiedArray = tömbök.stream (strArray) .toArray (karakterlánc [] :: új); 

A nem primitív típusok esetében az objektumok sekély másolatát is elkészíti. További információkért Java 8 adatfolyamok, itt kezdheti.

6. Külső könyvtárak

Apache Commons 3 nevű segédprogramot kínál SerializationUtils amely biztosítja a klón (…) módszer. Nagyon hasznos, ha egy nem primitív típusú tömb mély másolatát kell készítenünk. Innen letölthető, és Maven-függősége:

 org.apache.commons commons-lang3 3.5 

Vessünk egy pillantást egy tesztesetre:

public class Alkalmazott megvalósítja a Serializálható {// mezők // szabványos getterek és beállítók} Employee [] alkalmazottak = createEmployeesArray (); Alkalmazott [] copiedArray = SerializationUtils.clone (alkalmazottak); 
alkalmazottak [0] .setName (alkalmazottak [0] .getName () + "_Changed"); assertFalse (copyiedArray [0] .getName (). egyenlő (alkalmazottak [0] .getName ()));

Ez az osztály megköveteli, hogy minden objektumnak végre kell hajtania a Sorosítható felület. A teljesítmény szempontjából lassabban másolhatók, mint az objektumgrafikonunkban található egyes objektumokhoz kézzel írott klón módszerek.

7. Következtetés

Ebben az oktatóanyagban megvizsgáltuk a tömb Java-ba másolásának különféle lehetőségeit.

Az alkalmazandó módszer elsősorban a pontos forgatókönyvtől függ. Amíg egy primitív tömböt használunk, használhatjuk a Rendszer és Tömbök osztályok. A teljesítményben nem lehet különbség.

Nem primitív típusok esetén, ha egy tömb mély másolatát kell készítenünk, használhatjuk a SerializationUtils vagy kifejezetten klónozási módszereket adjunk osztályainkhoz.

És mint mindig, az ebben a cikkben bemutatott példák a GitHubon keresztül elérhetők.