Operacije nizova u Javi

1. Pregled

Bilo koji programer Java zna da stvaranje čistog, učinkovitog rješenja u radu s operacijama polja nije uvijek lako postići. Ipak, oni su središnji dio ekosustava Java - i s njima ćemo se morati nositi u nekoliko navrata.

Iz tog razloga dobro je imati 'varalicu' - sažetak najčešćih postupaka koji će nam pomoći u bržem rješavanju zagonetke. Ovaj će vam vodič dobro doći u tim situacijama.

2. Nizovi i klase pomoćnika

Prije nego što nastavite, korisno je shvatiti što je niz u Javi i kako ga koristiti. Ako prvi put radite s njim na Javi, predlažemo da pogledate ovaj prethodni post u kojem smo obradili sve osnovne koncepte.

Napominjemo da su osnovne operacije koje niz podržava na određeni način ograničene. Nerijetko se vide složeni algoritmi za izvršavanje relativno jednostavnih zadataka kada su u pitanju nizovi.

Iz tog razloga, za većinu naših operacija koristit ćemo pomoćne klase i metode koje će nam pomoći: Nizovi klase koju pružaju Java i Apacheovi ArrayUtils jedan.

Da bismo potonje uključili u naš projekt, morat ćemo dodati ovisnost Apache Commons:

 org.apache.commons commons-lang3 3.8.1 

Najnoviju verziju ovog artefakta možemo provjeriti na Maven Central.

3. Nabavite prvi i posljednji element niza

Ovo je jedan od najčešćih i najjednostavnijih zadataka zahvaljujući prirodi nizova pristupa po indeksu.

Počnimo s deklariranjem i inicijalizacijom datoteke int niz koji će se koristiti u svim našim primjerima (osim ako ne navedemo drugačije):

int [] niz = novi int [] {3, 5, 2, 5, 14, 4};

Znajući da je prva stavka niza povezana s vrijednošću indeksa 0 i da ima duljina atribut koji možemo koristiti, onda je jednostavno shvatiti kako možemo dobiti ova dva elementa:

int firstItem = niz [0]; int lastItem = niz [niz.duljina - 1];

4. Dobijte slučajnu vrijednost iz niza

Korištenjem java.util.Slučajno objekt možemo lako dobiti bilo koju vrijednost iz našeg niza:

int anyValue = niz [novi Random (). nextInt (niz.duljina)];

5. Dodajte novu stavku u niz

Kao što znamo, nizovi imaju fiksnu veličinu vrijednosti. Stoga ne možemo samo dodati stavku i premašiti ovo ograničenje.

Morat ćemo započeti deklariranjem novog, većeg polja i kopirati elemente osnovnog niza u drugi.

Srećom, Nizovi klasa pruža praktičnu metodu za repliciranje vrijednosti niza u novu strukturu različite veličine:

int [] newArray = Arrays.copyOf (niz, niz.duljina + 1); newArray [newArray.length - 1] = newItem;

Po želji, ako ArrayUtils klasa je dostupna u našem projektu, možemo je iskoristiti dodaj metodu (ili njegov Dodaj Sve alternativa) kako bismo ostvarili svoj cilj u jednostrukoj izjavi:

int [] newArray = ArrayUtils.add (niz, newItem);

Kao što možemo zamisliti, ova metoda ne mijenja original niz objekt; moramo njegov izlaz dodijeliti novoj varijabli.

6. Umetnite vrijednost između dvije vrijednosti

Zbog svog karaktera indeksiranih vrijednosti, umetanje stavke u niz između dvije druge nije trivijalan posao.

Apache je ovo smatrao tipičnim scenarijem i u njega primijenio metodu ArrayUtils razred za pojednostavljenje rješenja:

int [] largerArray = ArrayUtils.insert (2, niz, 77);

Moramo odrediti indeks u koji želimo umetnuti vrijednost, a izlaz će biti novi niz koji sadrži veći broj elemenata.

Posljednji argument je argument varijable (a.k.a. vararg) tako da u niz možemo umetnuti bilo koji broj predmeta.

7. Usporedite dva niza

Iako su nizovi Objekts i stoga pružaju jednako metodu koriste zadanu implementaciju, oslanjajući se samo na referentnu jednakost.

U svakom slučaju možemo se pozvati na java.util.Arraysjednako metoda za provjeru sadrže li dva objekta niza iste vrijednosti:

boolean areEqual = Nizovi.equals (niz1, niz2);

Napomena: ova metoda nije učinkovita za nazubljene nizove. Prikladna metoda za provjeru jednakosti višedimenzionalnih struktura je Nizovi.deepEquals jedan.

8. Provjerite je li niz prazan

Ovo je jednostavan zadatak imajući na umu da možemo koristiti duljina atribut nizova:

boolean isEmpty = niz == null || niz.duljina == 0;

Štoviše, mi također imamo nul-sigurnu metodu u ArrayUtils pomoćna klasa koju možemo koristiti:

boolean isEmpty = ArrayUtils.isEmpty (niz);

Ova funkcija još uvijek ovisi o duljini strukture podataka koja nule i prazne pod nizove smatra i valjanim vrijednostima, pa ćemo morati pripaziti na ove rubne slučajeve:

// To su prazni nizovi Integer [] array1 = {}; Cijeli broj [] array2 = null; Integer [] array3 = novi Integer [0]; // Sve ovo NEĆE se smatrati praznim Integer [] array3 = {null, null, null}; Cijeli broj [] [] niz4 = {{}, {}, {}}; Integer [] array5 = novi Integer [3];

9. Kako promiješati elemente niza

Da bismo promiješali stavke u nizu, možemo koristiti ArrayUtilZnačajka:

ArrayUtils.shuffle (niz);

Ovo je poništiti metoda i djeluje na stvarnim vrijednostima niza.

10. Kutija i raspakiraj nizove

Često nailazimo na metode koje podržavaju samo Objektnizovi na bazi.

Opet ArrayUtils klasa pomoćnika dobro dođe za dobivanje verzije našeg primitivnog polja u boksu:

Cijeli broj [] lista = ArrayUtils.toObject (niz);

Moguća je i inverzna operacija:

Cijeli broj [] objectArray = {3, 5, 2, 5, 14, 4}; int [] niz = ArrayUtils.toPrimitive (objectArray);

11. Uklonite duplikate iz niza

Najlakši način uklanjanja duplikata je pretvaranjem niza u Postavi provedba.

Kao što možda znamo, Kolekcijas koriste generičke i stoga ne podržavaju primitivne tipove.

Iz tog razloga, ako ne rukujemo objektno zasnovanim nizovima kao u našem primjeru, prvo ćemo morati uokviriti svoje vrijednosti:

// Cjeloviti okvir [] popis = ArrayUtils.toObject (niz); // Uklanjanje duplikata Set set = new HashSet (Arrays.asList (list)); // Stvaranje niza i otpakiranje vrati ArrayUtils.toPrimitive (set.toArray (novi cijeli broj [set.size ()]));

Napomena: možemo koristiti druge tehnike za pretvaranje između polja i a Postavi objekt također.

Također, ako želimo sačuvati redoslijed svojih elemenata, moramo koristiti drugačiji Postavi provedba, kao što je a LinkedHashSet.

12. Kako ispisati niz

Isto kao i kod jednako metoda, niz toString funkcija koristi zadanu implementaciju koju pruža Objekt klase, što nije baš korisno.

Oba Nizovi i ArrayUtils klase se isporučuju sa svojim implementacijama za pretvorbu podatkovnih struktura u čitljive Niz.

Osim malo drugačijeg formata koji koriste, najvažnija je razlika u načinu na koji postupaju s višedimenzionalnim objektima.

Klasa Java Util nudi dvije statičke metode koje možemo koristiti:

  • toString: ne radi dobro s nazubljenim nizovima
  • deepToString: podržava bilo koji Objektnizovi na bazi, ali se ne prevode s primitivnim argumentima niza

S druge strane, Apacheova implementacija nudi jedan toString metoda koja u svakom slučaju ispravno radi:

Niz arrayAsString = ArrayUtils.toString (niz);

13. Mapiranje niza u drugu vrstu

Često je korisno primijeniti operacije na svim stavkama niza, moguće ih pretvoriti u drugu vrstu objekta.

Imajući ovaj cilj na umu, pokušat ćemo stvoriti fleksibilnu pomoćnu metodu koristeći Generics:

javni statički U [] mapObjectArray (T [] niz, funkcija funkcija, klasa targetClazz) {U [] newArray = (U []) Array.newInstance (targetClazz, array.length); for (int i = 0; i <niz.duljina; i ++) {newArray [i] = function.apply (niz [i]); } return newArray; }

Ako u našem projektu ne koristimo Javu 8, možemo odbaciti Funkcija argument i stvorite metodu za svako mapiranje koje moramo provesti.

Sada našu generičku metodu možemo ponovno koristiti za različite operacije. Stvorimo dva test slučaja koja će to ilustrirati:

@Test public void whenMapArrayMultiplyingValues_thenReturnMultifiedArray () {Integer [] multifiedExpectedArray = new Integer [] {6, 10, 4, 10, 28, 8}; Integer [] output = MyHelperClass.mapObjectArray (niz, vrijednost -> vrijednost * 2, Integer.class); assertThat (output) .containsExactly (pomnoženiExpectedArray); } @Test public void whenMapDividingObjectArray_thenReturnMultifiedArray () {Double [] multiptedExpectedArray = new Double [] {1.5, 2.5, 1.0, 2.5, 7.0, 2.0}; Dvostruki [] izlaz = MyHelperClass.mapObjectArray (niz, vrijednost -> vrijednost / 2.0, Double.class); assertThat (output) .containsExactly (pomnoženiExpectedArray); }

Za primitivne tipove prvo ćemo morati uokviriti svoje vrijednosti.

Kao alternativu, možemo se obratiti Java 8's Streams da nam izvrši mapiranje.

Morat ćemo transformirati niz u Stream od Objektprvo. To možemo učiniti s Nizovi.tok metoda.

Na primjer, ako želimo mapirati svoj int vrijednosti prema običaju Niz predstavljanja, implementirat ćemo ovo:

String [] stringArray = Arrays.stream (niz) .mapToObj (vrijednost -> String.format ("Vrijednost:% s", vrijednost)) .toArray (String [] :: novo);

14. Filtriranje vrijednosti u nizu

Filtriranje vrijednosti iz zbirke čest je zadatak koji ćemo možda morati obaviti u više navrata.

To je zato što u vrijeme kada stvaramo niz koji će primati vrijednosti ne možemo biti sigurni u njegovu konačnu veličinu. Stoga, oslonit ćemo se na Streams pristup opet.

Zamislite da iz polja želimo ukloniti sve neparne brojeve:

int [] evenArray = Nizovi.stream (niz) .filter (vrijednost -> vrijednost% 2 == 0) .toArray ();

15. Ostale uobičajene operacije niza

Postoji, naravno, puno drugih operacija niza koje ćemo možda trebati izvesti.

Osim onih prikazanih u ovom vodiču, opsežno smo obradili i druge operacije u namjenskim postovima:

  • Provjerite sadrži li Java niz vrijednost
  • Kako kopirati niz u Javi
  • Uklanjanje prvog elementa niza
  • Pronalaženje min i max u nizu s Javom
  • Pronađite zbroj i prosjek u Java nizu
  • Kako invertirati niz u Javi
  • Pridružite se i podijelite nizove i zbirke na Javi
  • Kombiniranje različitih vrsta kolekcija u Javi
  • Pronađi sve parove brojeva u nizu koji se zbrajaju s danim zbrojem
  • Razvrstavanje u Javi
  • Učinkovit kalkulator frekvencije riječi u Javi
  • Sortiranje umetanja na Javi

16. Zaključak

Nizovi su jedna od osnovnih funkcionalnosti Jave, pa je stoga zaista važno razumjeti njihov rad i znati što s njima možemo, a što ne možemo.

U ovom smo tutorijalu naučili kako u uobičajenim scenarijima možemo na odgovarajući način rukovati operacijama niza.

Kao i uvijek, puni izvorni kod radnih primjera dostupan je na našem Github repo-u.