Tömbműveletek Java-ban

1. Áttekintés

Bármely Java-fejlesztő tudja, hogy tiszta és hatékony megoldás előállítása tömbműveletekkel való munkavégzés során nem mindig könnyű. Ennek ellenére a Java ökoszisztémájának központi darabjai - és többször is foglalkoznunk kell velük.

Emiatt jó, ha van egy „csalólap” - a leggyakoribb eljárások összefoglalása, amelyek segítenek a rejtvény gyors megoldásában. Ez a bemutató hasznos lesz ezekben a helyzetekben.

2. Tömbök és segítő osztályok

A folytatás előtt hasznos megérteni, hogy mi a tömb a Java-ban, és hogyan kell használni. Ha először dolgozik vele Java-ban, javasoljuk, hogy nézze meg ezt az előző bejegyzést, ahol az összes alapvető fogalmat bemutattuk.

Felhívjuk figyelmét, hogy a tömb által támogatott alapvető műveletek bizonyos módon korlátozottak. Nem ritka összetett algoritmusok láthatók viszonylag egyszerű feladatok végrehajtására, amikor tömbökről van szó.

Ezért legtöbb műveletünk során segítő osztályokat és módszereket fogunk használni a segítségünkre: a Tömbök osztály, amelyet a Java és az Apache szolgáltat ArrayUtils egy.

Ez utóbbinak a projektünkbe történő felvételéhez hozzá kell adnunk az Apache Commons függőséget:

 org.apache.commons commons-lang3 3.8.1 

Megtekinthetjük a műtárgy legújabb verzióját a Maven Central oldalon.

3. Szerezze meg egy tömb első és utolsó elemét

Ez az egyik leggyakoribb és legegyszerűbb feladat a tömbök indexenkénti hozzáférésének köszönhetően.

Kezdjük azzal, hogy deklaráljuk és inicializáljuk a int tömb, amelyet minden példánkban használni fogunk (hacsak másként nem adjuk meg):

int [] tömb = új int [] {3, 5, 2, 5, 14, 4};

Annak tudatában, hogy egy tömb első eleme a 0 indexértékhez van társítva, és van egy hossz attribútum, amelyet használhatunk, akkor egyszerű kitalálni, hogyan kaphatjuk meg ezt a két elemet:

int firstItem = tömb [0]; int lastItem = tömb [tömb.hossz - 1];

4. Szerezzen véletlenszerű értéket egy tömbből

A java.util.Random objektum esetén bármilyen értéket könnyen megszerezhetünk tömbünkből:

int anyValue = tömb [új Random (). nextInt (tömb.hossz)];

5. Csatoljon egy új elemet egy tömbhöz

Mint tudjuk, a tömbök rögzített méretű értékeket tárolnak. Ezért nem csak egy elemet adhatunk hozzá, és nem léphetjük túl ezt a korlátot.

Először egy új, nagyobb tömb deklarálásával kell kezdeni, és át kell másolnunk az alap tömb elemeit a másodikba.

Szerencsére a Tömbök osztály hasznos módszert kínál egy tömb értékeinek új, különböző méretű struktúrára történő replikálására:

int [] newArray = Tömbök.copyOf (tömb, tömb.hossz + 1); newArray [newArray.length - 1] = newItem;

Opcionálisan, ha a ArrayUtils osztály elérhető a projektünkben, ki tudjuk használni add metódus (vagy annak az összes hozzáadása alternatíva), hogy célkitűzésünket egy vonalas kijelentéssel teljesítsük:

int [] newArray = ArrayUtils.add (tömb, newItem);

Mint elképzelhetjük, ez a módszer nem módosítja az eredetit sor tárgy; új változóhoz kell rendelnünk a kimenetét.

6. Helyezzen be egy értéket két érték közé

Indexelt értékű jellege miatt egy elem tömbbe illesztése két másik közé nem triviális feladat.

Az Apache ezt tipikus forgatókönyvnek tartotta, és egy módszert alkalmazott benne ArrayUtils osztály a megoldás egyszerűsítése érdekében:

int [] nagyobbArray = ArrayUtils.insert (2, tömb, 77);

Meg kell adnunk azt az indexet, amelybe be akarjuk szúrni az értéket, és a kimenet egy új tömb lesz, amely nagyobb számú elemet tartalmaz.

Az utolsó argumentum változó argumentum (más néven vararg) így tetszőleges számú elemet beilleszthetünk a tömbbe.

7. Hasonlítsa össze a két tömböt

Annak ellenére, hogy tömbök vannak Tárgys ezért biztosítanak egy egyenlő módszerrel, az alapértelmezett megvalósítását használják, csak a referenciaegyenlőségre támaszkodva.

Bárhogy is hívhatjuk a java.util.A Arraysegyenlő módszer annak ellenőrzésére, hogy két tömbobjektum azonos értékeket tartalmaz-e:

logikai areEqual = Tömbök.egyenlő (tömb1, tömb2);

Megjegyzés: ez a módszer nem hatékony szaggatott tömbök esetén. A megfelelő módszer a többdimenziós struktúrák egyenlőségének ellenőrzésére a Arrays.deepEquals egy.

8. Ellenőrizze, hogy egy tömb üres-e

Ez egy bonyolult feladat, szem előtt tartva, hogy használhatjuk a hossz tömbök attribútuma:

logikai isEmpty = tömb == null || tömb.hossz == 0;

Sőt, van egy semleges módszerünk is a ArrayUtils segítő osztály, amelyet használhatunk:

logikai isEmpty = ArrayUtils.isEmpty (tömb);

Ez a függvény továbbra is az adatszerkezet hosszától függ, amely a nullákat és az üres résztömböket is érvényes értéknek tekinti, ezért ezeket az éles eseteket kell figyelnünk:

// Ezek üres tömbök Integer [] tömb1 = {}; Egész [[tömb2] = null; Egész [[tömb3] = új egész [0]; // Mindezeket NEM tekintjük üresnek Egész szám [] tömb3 = {null, null, null}; Egész szám [] [] tömb4 = {{}, {}, {}}; Egész [[tömb5] = új egész [3];

9. Hogyan keverjük össze egy tömb elemeit

A tömbben lévő elemek keveréséhez használhatjuk a ArrayUtilJellemzői:

ArrayUtils.shuffle (tömb);

Ez egy üres módszerrel és a tömb tényleges értékein mûködik.

10. Box és Unbox tömbök

Gyakran találkozunk olyan módszerekkel, amelyek csak támogatják Tárgyalapú tömbök.

Ismét a ArrayUtils a segítő osztály hasznos lehet primitív tömbünk dobozos változatának megszerzéséhez:

Egész szám [] lista = ArrayUtils.toObject (tömb);

Az inverz művelet is lehetséges:

Egész szám [] objectArray = {3, 5, 2, 5, 14, 4}; int [] tömb = ArrayUtils.toPrimitive (objectArray);

11. Távolítsa el a másolatokat egy tömbből

A duplikátumok eltávolításának legegyszerűbb módja a tömb átalakítása a-ba Készlet végrehajtás.

Mint tudjuk, Gyűjteménys használja a Generics-et, ezért nem támogatja a primitív típusokat.

Ezért, ha nem az objektumalapú tömböket kezeljük, mint a példánkban, akkor először be kell jelölnünk az értékeinket:

// Box Integer [] list = ArrayUtils.toObject (tömb); // Ismétlődések eltávolítása Set set = new HashSet (Arrays.asList (list)); // Tömb létrehozása és az unbox visszaküldése ArrayUtils.toPrimitive (set.toArray (new Integer [set.size ()]));

Megjegyzés: más technikákat is alkalmazhatunk a tömb és az a közötti átalakításra Készlet tárgy is.

Továbbá, ha meg kell őriznünk az elemeink sorrendjét, akkor mást kell használnunk Készlet megvalósítás, például a LinkedHashSet.

12. Hogyan nyomtassunk egy tömböt

Ugyanaz, mint a egyenlő módszer, a tömb Sztring függvény az alapértelmezett megvalósítást használja Tárgy osztály, ami nem túl hasznos.

Mindkét Tömbök és ArrayUtils osztályok szállítják megvalósításukkal az adatszerkezetek olvashatóvá alakítására Húr.

Az általuk kissé eltérő formátumon kívül a legfontosabb különbség az, hogy hogyan kezelik a többdimenziós tárgyakat.

A Java Util osztálya két statikus módszert kínál, amelyeket használhatunk:

  • Sztring: nem működik jól szaggatott tömbökkel
  • deepToString: bármelyiket támogatja Tárgytömbök, de nem fordít primitív tömb argumentumokkal

Másrészről, Az Apache megvalósítása egyetlen lehetőséget kínál Sztring minden esetben helyesen működő módszer:

String arrayAsString = ArrayUtils.toString (tömb);

13. Hozzon létre egy tömböt egy másik típushoz

Gyakran hasznos műveleteket alkalmazni az összes tömbelemre, esetleg átalakítani őket egy másik típusú objektummá.

Ezt a célt szem előtt tartva megpróbálunk létrehozni egy rugalmas segítő módszert a Generics segítségével:

public static U [] mapObjectArray (T [] tömb, Funkció függvény, Osztály targetClazz) {U [] newArray = (U []) Array.newInstance (targetClazz, tömb.hossz); for (int i = 0; i <tömb.hossz; i ++) {newArray [i] = function.apply (tömb [i]); } return newArray; }

Ha nem használjuk a Java 8-at a projektünkben, akkor eldobhatjuk a Funkció argumentumot, és hozzon létre egy módszert minden hozzárendeléshez, amelyet végre kell hajtanunk.

Most újra felhasználhatjuk általános módszerünket különböző műveletekhez. Hozzunk létre két tesztesetet ennek szemléltetésére:

@Test public void whenMapArrayMultiplyingValues_thenReturnMultipliedArray () {Egész szám [] multipliedExpectedArray = új egész szám [] {6, 10, 4, 10, 28, 8}; Egész szám [] output = MyHelperClass.mapObjectArray (tömb, érték -> érték * 2, Egész.osztály); assertThat (output) .containsExactly (multipliedExpectedArray); } @Test public void whenMapDividingObjectArray_thenReturnMultipliedArray () {Double [] multipliedExpectedArray = new Double [] {1.5, 2.5, 1.0, 2.5, 7.0, 2.0}; Dupla [] output = MyHelperClass.mapObjectArray (tömb, érték -> érték / 2.0, Dupla.osztály); assertThat (output) .containsExactly (multipliedExpectedArray); }

A primitív típusoknál először be kell jelölnünk az értékeinket.

Alternatív megoldásként fordulhatunk a Java 8 Streamjeihez, hogy elvégezzük a feltérképezést számunkra.

Át kell alakítanunk a tömböt a-vá Folyam nak,-nek Tárgys első. Megtehetjük a Tömbök.folyam módszer.

Például, ha térképünket akarjuk feltérképezni int értékeket egy szokásnak Húr képviselet, ezt megvalósítjuk:

String [] stringArray = Arrays.stream (tömb) .mapToObj (érték -> String.format ("Érték:% s", érték)) .toArray (String [] :: új);

14. Értékek szűrése egy tömbben

Az értékek kiszűrése a gyűjteményből egy gyakori feladat, amelyet többször is el kell végeznünk.

Ugyanis abban az időben, amikor létrehozzuk az értékeket fogadó tömböt, nem lehetünk biztosak a végleges méretében. Ebből kifolyólag, támaszkodunk a Folyams ismét közeledni.

Képzelje el, hogy az összes páratlan számot el akarjuk távolítani egy tömbből:

int [] evenArray = tömbök.folyam (tömb) .szűrő (érték -> érték% 2 == 0) .toArray ();

15. Egyéb közös tömb műveletek

Természetesen rengeteg más tömbművelet van, amelyeket végre kell hajtanunk.

Az ebben az oktatóanyagban bemutatottaktól eltekintve a külön bejegyzésekben szereplő egyéb műveletekről is részletesen beszámoltunk:

  • Ellenőrizze, hogy a Java tömb tartalmaz-e értéket
  • Tömb másolása Java-ban
  • Egy tömb első elemének eltávolítása
  • A Min és Max keresése egy tömbben Java-val
  • Keresse meg az összeget és az átlagot egy Java tömbben
  • Hogyan lehet átalakítani egy tömböt a Java-ban
  • Tömbök és gyűjtemények egyesítése és megosztása Java-ban
  • Különböző típusú gyűjtemények kombinálása a Java-ban
  • Találja meg az összes számpárot egy tömbben, amely összead egy adott összeget
  • Rendezés Java-ban
  • Hatékony szófrekvencia-számológép Java-ban
  • Beszúrás Rendezés Java-ban

16. Következtetés

A tömbök a Java egyik alapvető funkciója, ezért nagyon fontos megérteni a működésüket, és tudni, hogy mit tehetünk és mit nem.

Ebben az oktatóanyagban megtudtuk, hogyan kezelhetjük megfelelően a tömb műveleteket a szokásos esetekben.

Mint mindig, a működő példák teljes forráskódja elérhető a Github repóban.