Operácie s poľom v prostredí Java

1. Prehľad

Každý vývojár Java vie, že vytvorenie čistého a efektívneho riešenia pri práci s operáciami poľa nie je vždy ľahké dosiahnuť. Stále sú ústredným prvkom ekosystému Java - a budeme sa s nimi musieť vysporiadať pri niekoľkých príležitostiach.

Z tohto dôvodu je dobré mať „cheat sheet“ - súhrn najbežnejších postupov, ktoré nám pomôžu rýchlo sa s puzzle vyrovnať. V týchto situáciách sa vám tento návod bude hodiť.

2. Polia a triedy pomocníkov

Pred pokračovaním je užitočné pochopiť, čo je to pole v Jave a ako ho používať. Ak s ním pracujete v prostredí Java prvýkrát, odporúčame vám pozrieť sa na tento predchádzajúci príspevok, kde sme prebrali všetky základné pojmy.

Upozorňujeme, že základné operácie, ktoré pole podporuje, sú určitým spôsobom obmedzené. Nie je nezvyčajné vidieť zložité algoritmy na vykonávanie relatívne jednoduchých úloh, pokiaľ ide o polia.

Z tohto dôvodu budeme pri väčšine našich operácií používať pomocné triedy a metódy: Polia triedy poskytované programami Java a Apache ArrayUtils jeden.

Aby sme to mohli zahrnúť do nášho projektu, budeme musieť pridať závislosť Apache Commons:

 org.apache.commons commons-lang3 3.8.1 

Môžeme sa pozrieť na najnovšiu verziu tohto artefaktu v Maven Central.

3. Získajte prvý a posledný prvok poľa

Toto je jedna z najbežnejších a najjednoduchších úloh vďaka charakteru polí typu access-by-index.

Začnime vyhlásením a inicializáciou súboru int pole, ktoré sa použije vo všetkých našich príkladoch (pokiaľ neurčíme inak):

int [] pole = nový int [] {3, 5, 2, 5, 14, 4};

Vedieť, že prvá položka v poli je spojená s hodnotou indexu 0 a že má a dĺžka atribút, ktorý môžeme použiť, potom je ľahké zistiť, ako môžeme získať tieto dva prvky:

int firstItem = pole [0]; int lastItem = pole [pole.length - 1];

4. Získajte náhodnú hodnotu z poľa

Použitím java.util.Random objekt môžeme ľahko získať akúkoľvek hodnotu z nášho poľa:

int anyValue = array [new Random (). nextInt (array.length)];

5. Pripojte novú položku k poľu

Ako vieme, polia majú pevnú veľkosť hodnôt. Preto nemôžeme iba pridať položku a prekročiť tento limit.

Budeme musieť začať vyhlásením nového, väčšieho poľa a skopírovať prvky základného poľa do druhého.

Našťastie Polia class poskytuje praktickú metódu na replikáciu hodnôt poľa do novej štruktúry inej veľkosti:

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

Prípadne, ak ArrayUtils triedy je prístupná v našom projekte, môžeme ju využiť pridať metódu (alebo jeho pridať všetko alternatívu) na splnenie nášho cieľa v jednom riadku:

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

Ako si vieme predstaviť, táto metóda nemení pôvodný text pole predmet; musíme jej výstup priradiť k novej premennej.

6. Vložte hodnotu medzi dve hodnoty

Vloženie znaku do poľa medzi dva ďalšie nie je kvôli jeho znaku indexovaných hodnôt triviálna práca.

Apache to považoval za typický scenár a implementoval doň metódu ArrayUtils triedy na zjednodušenie riešenia:

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

Musíme určiť index, do ktorého chceme vložiť hodnotu, a výstupom bude nové pole obsahujúce väčší počet prvkov.

Posledný argument je variabilný argument (a.k.a. vararg), takže do poľa môžeme vložiť ľubovoľný počet položiek.

7. Porovnajte dve polia

Aj keď polia sú Objekts a preto poskytujú rovná sa používajú predvolenú implementáciu, ktorá sa spolieha iba na referenčnú rovnosť.

Môžeme sa kedykoľvek dovolávať java.util.Arraysrovná sa metóda na kontrolu, či dva objekty poľa obsahujú rovnaké hodnoty:

boolean areEqual = Arrays.equals (pole1, pole2);

Poznámka: Táto metóda nie je účinná pre zubaté polia. Vhodnou metódou na overenie rovnosti viacrozmerných štruktúr je Arrays.deepEquals jeden.

8. Skontrolujte, či je pole prázdne

Toto je nekomplikované zadanie s ohľadom na to, že môžeme použiť dĺžka atribút polí:

boolean isEmpty = array == null || pole.length == 0;

Okrem toho máme v ArrayUtils pomocná trieda, ktorú môžeme použiť:

boolean isEmpty = ArrayUtils.isEmpty (pole);

Táto funkcia stále závisí od dĺžky dátovej štruktúry, ktorá za platné hodnoty považuje aj hodnoty null a prázdne podradené polia, takže budeme musieť dávať pozor na tieto okrajové prípady:

// Toto sú prázdne polia Integer [] pole1 = {}; Celé číslo [] pole2 = null; Celé číslo [] pole3 = nové celé číslo [0]; // Všetky tieto NEBUDÚ považované za prázdne Celé číslo [] pole3 = {null, null, null}; Celé číslo [] [] pole4 = {{}, {}, {}}; Celé číslo [] pole5 = nové celé číslo [3];

9. Ako zamiešať prvky poľa

Na zamiešanie položiek v poli môžeme použiť znak ArrayUtilFunkcia:

ArrayUtils.shuffle (pole);

Toto je neplatný metóda a pracuje na skutočných hodnotách poľa.

10. Polia typu Box a Unbox

Často sa stretávame s metódami, ktoré iba podporujú Objekt- polia na báze.

Opäť ArrayUtils trieda pomocníka sa hodí na získanie zabalenej verzie nášho primitívneho poľa:

Celé číslo [] list = ArrayUtils.toObject (pole);

Inverzná operácia je tiež možná:

Celé číslo [] objectArray = {3, 5, 2, 5, 14, 4}; int [] pole = ArrayUtils.toPrimitive (objectArray);

11. Odstráňte duplikáty z poľa

Najjednoduchší spôsob odstránenia duplikátov je prevedením poľa na a Nastaviť implementácia.

Ako možno vieme, Zbierkapoužívajú generiká, a preto nepodporujú primitívne typy.

Z tohto dôvodu, ak nespracovávame objektové polia ako v našom príklade, budeme musieť najskôr zabaliť naše hodnoty:

// Box Integer [] list = ArrayUtils.toObject (pole); // Odstrániť duplikáty Set set = new HashSet (Arrays.asList (list)); // Vytvoriť pole a vrátiť unbox return ArrayUtils.toPrimitive (set.toArray (new Integer [set.size ()])));

Poznámka: na prevod medzi poľom a a. Môžeme použiť ďalšie techniky Nastaviť objekt tiež.

Ak potrebujeme zachovať poradie našich prvkov, musíme použiť iný Nastaviť implementácia, ako je a LinkedHashSet.

12. Ako tlačiť pole

Rovnako ako v prípade rovná sa metóda, pole natiahnuť Funkcia používa predvolenú implementáciu poskytovanú Objekt triedy, čo nie je veľmi užitočné.

Oboje Polia a ArrayUtils triedy sa dodávajú s ich implementáciami na prevod dátových štruktúr na čitateľné String.

Okrem mierne odlišného formátu, ktorý používajú, je najdôležitejším rozdielom to, ako zaobchádzajú s viacrozmernými objektmi.

Trieda Java Util poskytuje dve statické metódy, ktoré môžeme použiť:

  • natiahnuť: nefunguje dobre so zubatými poľami
  • deepToString: podporuje všetky Objektpole založené na kompilácii, ale nekompilované s primitívnymi argumentmi poľa

Na druhej strane, Implementácia Apache ponúka jeden natiahnuť metóda, ktorá v každom prípade funguje správne:

String arrayAsString = ArrayUtils.toString (pole);

13. Namapujte pole na iný typ

Často je užitočné použiť operácie na všetky položky poľa a prípadne ich previesť na iný typ objektu.

S ohľadom na tento cieľ skúsime vytvoriť flexibilnú pomocnú metódu pomocou Generics:

public static U [] mapObjectArray (T [] pole, funkčná funkcia, trieda targetClazz) {U [] newArray = (U []) Array.newInstance (targetClazz, array.length); for (int i = 0; i <array.length; i ++) {newArray [i] = function.apply (pole [i]); } návrat newArray; }

Pokiaľ v našom projekte nepoužívame Java 8, môžeme zahodiť Funkcia argument a vytvorte metódu pre každé mapovanie, ktoré musíme vykonať.

Teraz môžeme našu generickú metódu znova použiť na rôzne operácie. Na ilustráciu vytvorme dva testovacie prípady:

@Test public void whenMapArrayMultiplyingValues_thenReturnMultipliedArray () {Integer [] multipliedExectedArray = new Integer [] {6, 10, 4, 10, 28, 8}; Celé číslo [] výstup = MyHelperClass.mapObjectArray (pole, hodnota -> hodnota * 2, Integer.class); assertThat (výstup) .containsExactly (multipliedExpectedArray); } @Test public void whenMapDividingObjectArray_thenReturnMultipliedArray () {Double [] multipliedExectedArray = new Double [] {1.5, 2.5, 1.0, 2.5, 7.0, 2.0}; Double [] výstup = MyHelperClass.mapObjectArray (pole, hodnota -> hodnota / 2.0, Double.class); assertThat (výstup) .containsExactly (multipliedExpectedArray); }

Pri primitívnych typoch budeme musieť najskôr skombinovať naše hodnoty.

Ako alternatívu sa môžeme obrátiť na prúdy Java 8 a vykonať mapovanie za nás.

Budeme musieť transformovať pole na a Prúd z Objekts prvý. Môžeme tak urobiť pomocou Polia.prúd metóda.

Napríklad, ak chceme zmapovať naše int hodnoty na zvyk String zastúpenie, implementujeme toto:

String [] stringArray = Arrays.stream (pole) .mapToObj (hodnota -> String.format ("hodnota:% s", hodnota)) .toArray (reťazec [] :: nový);

14. Filtrovanie hodnôt v poli

Filtrovanie hodnôt zo zbierky je bežná úloha, ktorú možno budeme musieť vykonať pri viacerých príležitostiach.

Je to tak preto, lebo v čase, keď vytvoríme pole, ktoré bude prijímať hodnoty, si nemôžeme byť istí jeho konečnou veľkosťou. Preto budeme sa spoliehať na Prúdopäť prístup.

Predstavte si, že chceme z poľa odstrániť všetky nepárne čísla:

int [] evenArray = Arrays.stream (pole) .filter (hodnota -> hodnota% 2 == 0) .toArray ();

15. Ďalšie bežné operácie s poľom

Existuje samozrejme veľa ďalších operácií s poľami, ktoré by sme možno potrebovali vykonať.

Okrem tých, ktoré sú uvedené v tomto výučbe, sme sa vo venovaných príspevkoch podrobne venovali ďalším operáciám:

  • Skontrolujte, či pole Java obsahuje hodnotu
  • Ako kopírovať pole v Jave
  • Odstránenie prvého prvku poľa
  • Hľadanie min a max v poli pomocou Java
  • Nájdite súčet a priemer v poli Java
  • Ako invertovať pole v Jave
  • Pripojte sa a rozdeľte polia a zbierky v Jave
  • Kombinácia rôznych typov zbierok v Jave
  • Nájdite všetky dvojice čísel v poli, ktoré predstavuje celkovú sumu
  • Triedenie v Jave
  • Efektívna kalkulačka frekvencie slov v Jave
  • Vkladanie Triedenie v Jave

16. Záver

Polia sú jednou z hlavných funkcií jazyka Java, a preto je skutočne dôležité pochopiť, ako fungujú, a vedieť, čo s nimi môžeme a čo nemôžeme robiť.

V tomto tutoriáli sme sa naučili, ako môžeme v bežných scenároch vhodne spracovať operácie s poľami.

Celý zdrojový kód pracovných príkladov je ako vždy k dispozícii v našom repo serveri Github.


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