Kako kopirati niz u Javi

1. Pregled

U ovom ćemo kratkom članku razmotriti različite metode kopiranja nizova u Javi. Kopija niza može se činiti trivijalnim zadatkom, ali može prouzročiti neočekivane rezultate i ponašanje programa ako se to ne učini pažljivo.

2. The Sustav Razred

Počnimo s osnovnom Java knjižnicom - System.arrayCopy (); ovo kopira niz iz izvornog polja u odredišni niz, započinjući akciju kopiranja s izvornog položaja na ciljni položaj do zadane duljine.

Broj elemenata kopiranih u ciljni niz jednak je navedenoj duljini. Pruža jednostavan način kopiranja podsljeda niza u drugi.

Ako je bilo koji od argumenata niza null, baca a NullPointerException a ako je bilo koji od argumenata cijelog broja negativan ili je izvan dosega, baca znak IndexOutOfBoundException.

Pogledajmo primjer kopiranja cijelog niza u drugi pomoću java.util.Sustav razred:

int [] niz = {23, 43, 55}; int [] kopirani niz = novi int [3]; System.arraycopy (niz, 0, kopiraniArray, 0, 3);

Argumenti koje uzima ova metoda su; izvorni niz, početni položaj za kopiranje iz izvornog polja, odredišni niz, početni položaj u odredišnom nizu i broj elemenata za kopiranje.

Pogledajmo još jedan primjer koji pokazuje kopiranje podsljeda iz izvornog polja na odredište:

int [] niz = {23, 43, 55, 12, 65, 88, 92}; int [] kopirani niz = novi int [3]; System.arraycopy (niz, 2, kopiraniArray, 0, 3); 
assertTrue (3 == kopiranoArray.length); assertTrue (copyMarray [0] == niz [2]); assertTrue (copyErray [1] == niz [3]); assertTrue (copyErray [2] == niz [4]); 

3. The Nizovi Razred

The Nizovi klasa također nudi višestruko preopterećene metode za kopiranje niza u drugi. Interno koristi isti pristup koji pruža Sustav razred koji smo vidjeli ranije. Uglavnom pruža dvije metode, kopija od(…) i copyRangeOf (…).

Pogledajmo kopija od prvi:

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

Važno je to napomenuti Nizovi razred koristi Math.min (…) za odabir minimuma duljine izvornog polja i vrijednosti novog parametra duljine za određivanje veličine rezultirajućeg polja.

Arrays.copyOfRange () uzima 2 parametra, 'iz' i 'do' uz parametar izvornog niza. Dobiveni niz uključuje 'iz' indeks, ali 'do' indeks je isključen. Pogledajmo primjer:

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

Obje ove metode napravite plitku kopiju objekata ako se primjenjuju na niz neprimitivnih vrsta objekata. Pogledajmo primjer testnog slučaja:

Employee [] copyErray = Arrays.copyOf (zaposlenici, zaposlenici.duljina); zaposlenici [0] .setName (zaposlenici [0] .getName () + "_Promijenjeni"); assertArrayEquals (kopiraniArray, niz);

Budući da je rezultat plitka kopija - promjena imena zaposlenika elementa izvornog niza uzrokovala je promjenu u nizu kopija.

I zato - ako želimo napraviti dubinsku kopiju neprimitivnih tipova - možemo se odlučiti za ostale opcije opisane u sljedećim odjeljcima.

4. Kopiraj niz s Object.clone ()

Object.clone () nasljeđuje se od Objekt klasa u nizu.

Kopirajmo prvo niz primitivnih tipova metodom clone:

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

I dokaz da djeluje:

assertArrayEquals (kopiraniArray, niz); niz [0] = 9; assertTrue (copyErray [0]! = niz [0]);

Gornji primjer pokazuje da imaju isti sadržaj nakon kloniranja, ali sadrže različite reference, tako da bilo koja promjena u bilo kojem od njih neće utjecati na drugu.

S druge strane, ako kloniramo niz neprimitivnih tipova pomoću iste metode, tada će rezultati biti drugačiji.

Stvara plitka kopija elemenata niza neprimitivnog tipa, čak i ako klasa zatvorenog objekta implementira Klonirajući sučelje i poništava klon() metoda iz Objekt razred.

Pogledajmo primjer:

adresa javne klase implementira Cloneable {// ... @Override zaštićeni objektni klon () baca CloneNotSupportedException {super.clone (); Adresa adresa = nova adresa (); address.setCity (this.city); Povratna adresa; }} 

Možemo testirati našu implementaciju stvaranjem novog niza adresa i pozivanjem naše klon() metoda:

Adresa [] adrese = createAddressArray (); Adresa [] copyErray = adrese.clone (); adrese [0] .setCity (adrese [0] .getCity () + "_Promijenjeno"); 
assertArrayEquals (kopiraniArray, adrese);

Ovaj primjer pokazuje da bi svaka promjena u izvornom ili kopiranom nizu uzrokovala promjenu u drugom, čak i kad su zatvoreni objekti Klonirajući.

5. Korištenje Stream API

Ispada, Stream API možemo koristiti i za kopiranje nizova. Pogledajmo primjer:

Niz [] strArray = {"narančasta", "crvena", "zelena '"}; String [] copiedArray = Arrays.stream (strArray) .toArray (String [] :: new); 

Za ne-primitivne tipove, također će napraviti plitku kopiju objekata. Da biste saznali više o Java 8 strujanja, možete započeti ovdje.

6. Vanjske knjižnice

Apache Commons 3 nudi klasu korisnosti tzv Korištenje serializacije koji pruža a klon(…) metoda. Vrlo je korisno ako trebamo napraviti dubinsku kopiju niza neprimitivnih tipova. Može se preuzeti ovdje, a ovisnost o Mavenu je:

 org.apache.commons commons-lang3 3.5 

Pogledajmo jedan testni slučaj:

javna klasa Employee implementira Serializable {// fields // standard getters and setters} Employee [] zaposlenici = createEfficieesArray (); Zaposlenik [] copyErray = SerializationUtils.clone (zaposlenici); 
zaposlenici [0] .setName (zaposlenici [0] .getName () + "_Promijenjeni"); assertFalse (copyIrray [0] .getName (). jednako (zaposlenici [0] .getName ()));

Ova klasa zahtijeva da svaki objekt treba implementirati Serijalizirati sučelje. Što se tiče izvedbe, to je sporije od metoda kloniranja koje su ručno napisane za kopiranje svakog od objekata u našem grafu objekata.

7. Zaključak

U ovom smo tutorijalu pogledali razne mogućnosti kopiranja niza u Javi.

Metoda koja se koristi uglavnom ovisi o točnom scenariju. Sve dok koristimo primitivni niz polja, možemo koristiti bilo koju od metoda koje nudi Sustav i Nizovi razreda. Ne bi trebalo biti nikakve razlike u izvedbi.

Za neprimitivne tipove, ako moramo napraviti dubinsku kopiju niza, možemo koristiti Korištenje serializacije ili izričito dodajte metode kloniranja u naše klase.

Kao i uvijek, primjeri prikazani u ovom članku dostupni su na više od GitHub-a.