Sprievodca programom Java 8 forEach

1. Prehľad

Predstavený v prostredí Java 8, pre každý slučka poskytuje programátorom nový, stručný a zaujímavý spôsob iterácie zbierky.

V tomto článku uvidíme, ako sa používa pre každý so zbierkami, aký druh argumentu je potrebný a ako sa táto slučka líši od vylepšenej pre-slučku.

Ak potrebujete oprášiť niektoré koncepty Java 8, máme pre vás zbierku článkov, ktoré vám môžu pomôcť.

2. Základy pre každý

V Jave sa Zbierka rozhranie má Iterable ako svoje super rozhranie - a počnúc Java 8 má toto rozhranie nové API:

void forEach (akcia spotrebiteľa)

Jednoducho povedané, Javadoc z pre každý štatistiky, že to „Vykonáva danú akciu pre každý prvok Iterable, kým nebudú spracované všetky prvky alebo kým akcia nevyvolá výnimku.“

A tak, s pre každý, môžeme iterovať cez kolekciu a vykonať danú akciu pre každý prvok, ako každý iný Iterátor.

Napríklad a pre-slučku verzia iterácie a tlače a Zbierka z Struny:

pre (Názov reťazca: mená) {System.out.println (meno); }

Toto môžeme napísať pomocou pre každý ako:

names.forEach (name -> {System.out.println (name);});

3. Pomocou pre každý Metóda

Používame pre každý iterovať zbierku a vykonať určitú akciu s každým prvkom. Akcia, ktorá sa má vykonať, je obsiahnutá v triede, ktorá implementuje Spotrebiteľ rozhranie a je odovzdané pre každý ako argument.

The Spotrebiteľ rozhranie je funkčné rozhranie (rozhranie s jedinou abstraktnou metódou). Prijíma vstup a nevracia žiadny výsledok.

Tu je definícia:

@FunctionalInterface verejné rozhranie Consumer {void accept (T t); }

Preto každá implementácia, napríklad spotrebiteľ, ktorý jednoducho vytlačí a String:

Consumer printConsumer = new Consumer () {public void accept (názov reťazca) {System.out.println (názov); }; };

možno odovzdať pre každý ako argument:

names.forEach (printConsumer);

To však nie je jediný spôsob uskutočnenia akcie prostredníctvom spotrebiteľa a použitia pre každý API.

Pozrime sa na 3 najpopulárnejšie spôsoby, ako budeme používať pre každý metóda:

3.1. Anonymný Spotrebiteľ Implementácia

Môžeme vytvoriť inštanciu implementácie Spotrebiteľ rozhranie pomocou anonymnej triedy a potom ho použiť ako argument pre pre každý metóda:

Consumer printConsumer = new Consumer () {public void accept (String name) {System.out.println (name); }}; names.forEach (printConsumer);

To funguje dobre, ale ak analyzujeme v príklade vyššie, uvidíme, že skutočnou časťou, ktorá sa bude používať, je kód vo vnútri súhlasiť() metóda.

Aj keď sú výrazy lambda v súčasnosti normou a ľahším spôsobom, ako to urobiť, stále stojí za to vedieť, ako implementovať Spotrebiteľ rozhranie.

3.2. Lambda výraz

Hlavnou výhodou funkčných rozhraní Java 8 je, že môžeme použiť výrazy Lambda na ich vytvorenie inštancie a vyhnúť sa použitiu objemných anonymných implementácií tried.

Ako Spotrebiteľ Rozhranie je funkčné rozhranie, ktoré môžeme vyjadriť v lambde vo forme:

(argument) -> {// body}

Preto náš printConsumer zjednodušuje:

meno -> System.out.println (názov)

A môžeme to odovzdať pre každý ako:

names.forEach (name -> System.out.println (name));

Od zavedenia výrazov Lambda v prostredí Java 8 je toto pravdepodobne najbežnejší spôsob použitia pre každý metóda.

Lambdy majú skutočne skutočnú krivku učenia, takže ak ste začínali, táto príprava obsahuje niekoľko osvedčených postupov pri práci s novou jazykovou funkciou.

3.3. Odkaz na metódu

Môžeme použiť syntax odkazu na metódu namiesto normálnej syntaxe Lambda, kde už existuje metóda na vykonanie operácie v triede:

names.forEach (System.out :: println);

4. Práca s pre každý

4.1. Iterácia nad zbierkou

Akýkoľvek iterovateľný typu Zbierka - zoznam, zostava, poradie atď. majú rovnakú syntax pre použitie pre každý.

Preto, ako sme už videli, iterovať prvky zoznamu:

Názvy zoznamu = Arrays.asList ("Larry", "Steve", "James"); names.forEach (System.out :: println);

Podobne pre sadu:

Set uniqueNames = new HashSet (Arrays.asList ("Larry", "Steve", "James")); uniqueNames.forEach (System.out :: println);

Alebo povedzme pre a Fronta čo je tiež a Zbierka:

Queue namesQueue = new ArrayDeque (Arrays.asList ("Larry", "Steve", "James")); namesQueue.forEach (System.out :: println);

4.2. Iterácia nad mapou - použitie máp pre každý

Mapy nie sú Iterable, ale robia poskytujú svoj vlastný variant pre každý ktorý prijíma a BiConsumer.

A BiConsumer bol zavedený namiesto Spotrebiteľ v Iterable pre každý aby bolo možné vykonať akciu ako na kľúči, tak na hodnote a Mapa súčasne.

Vytvorme a Mapa ktoré majú záznamy:

Names namesMap = new HashMap (); namesMap.put (1, "Larry"); namesMap.put (2, "Steve"); namesMap.put (3, "James");

Ďalej to zopakujme namesMap pomocou máp pre každý:

namesMap.forEach ((kľúč, hodnota) -> System.out.println (kľúč + "" + hodnota));

Ako vidíme tu, použili sme a BiConsumer:

(kľúč, hodnota) -> System.out.println (kľúč + "" + hodnota)

iterovať nad položkami súboru Mapa.

4.3. Iterácia cez a Mapa - iteráciou entrySet

Môžeme tiež iterovať Sada položiek a Mapa pomocou Iterable pre každý.

Odkedy záznamy a Mapa sú uložené v a Nastaviť zavolal Sada položiek, môžeme to iterovať pomocou a pre každý:

namesMap.entrySet (). forEach (entry -> System.out.println (entry.getKey () + "" + entry.getValue ()));

5. Foreach vs For-Loop

Z jednoduchého hľadiska poskytujú obe slučky rovnakú funkcionalitu - prechádzajú prvky v kolekcii.

Hlavný rozdiel medzi nimi dvoma je, že ide o rôzne iterátory - vylepšené pre-slučku je externý iterátor, zatiaľ čo nový pre každý metóda je interná.

5.1. Interný iterátor - pre každý

Tento typ iterátora riadi iteráciu na pozadí a ponecháva programátorovi iba kódovať, čo sa má robiť s prvkami kolekcie.

Namiesto toho iterátor spravuje iteráciu a zaisťuje postupné spracovanie prvkov.

Pozrime sa na príklad interného iterátora:

names.forEach (name -> System.out.println (name));

V pre každý vyššie, môžeme vidieť, že poskytnutý argument je výraz lambda. To znamená, že metódu stačí vedieť čo sa má robiť a o celú prácu pri iterácii sa bude starať interne.

5.2. Externý iterátor - pre-slučku

Externé iterátory mixujú čo a ako slučka sa má urobiť.

Vyčíslenia, Iterátory a vylepšené pre-slučku sú všetky externé iterátory (pamätajte na metódy iterátor (),Ďalšie() alebo hasNext () ? ). Vo všetkých týchto iterátoroch je našou úlohou špecifikovať, ako vykonávať iterácie.

Zvážte túto známu slučku:

pre (Názov reťazca: mená) {System.out.println (meno); }

Aj keď sa výslovne nedovolávame hasNext () alebo Ďalšie() pri iterácii zoznamu používa základný kód, ktorý umožňuje túto iteráciu, tieto metódy. To znamená, že zložitosť týchto operácií je pred programátorom skrytá, ale stále existuje.

Na rozdiel od interného iterátora, v ktorom kolekcia robí samotnú iteráciu, tu vyžadujeme externý kód, ktorý vyradí každý prvok z kolekcie.

6. Záver

V tomto článku sme ukázali, že pre každý slučka je pohodlnejšia ako obvykle pre-slučku.

Tiež sme videli, ako pre každý metóda funguje a aký druh implementácie je možné prijať ako argument, aby bolo možné vykonať akciu s každým prvkom v zbierke.

Nakoniec sú všetky útržky použité v tomto článku k dispozícii v našom úložisku Github.


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