Úvod do služby jOOL
1. Prehľad
V tomto článku sa pozrieme na jOOLknižnica - ďalší produkt z jOOQ.
2. Závislosť od Maven
Začnime tým, že do vašej pridáme závislosť Maven pom.xml:
org.jooq jool 0.9.12
Najnovšiu verziu nájdete tu.
3. Funkčné rozhrania
V prostredí Java 8 sú funkčné rozhrania dosť obmedzené. Prijímajú maximálny počet dvoch parametrov a nemajú veľa ďalších funkcií.
jOOL to opravuje preukázaním súboru nových funkčných rozhraní, ktoré dokážu prijať aj 16 parametrov (z Funkcia1 až Funkcia16) a sú obohatené o ďalšie užitočné metódy.
Napríklad na vytvorenie funkcie, ktorá má tri argumenty, môžeme použiť Funkcia 3:
Funkcia3 dĺžkaSum = (v1, v2, v3) -> v1.length () + v2.length () + v3.length ();
V čistej Jave by ste si to museli implementovať sami. Okrem toho majú funkčné rozhrania z jOOL svoju metódu applyPartially () ktorý nám umožňuje ľahko vykonať čiastočnú aplikáciu:
Funkcia2 addTwoNumbers = (v1, v2) -> v1 + v2; Function1 addToTwo = addTwoNumbers.applyPartially (2); Výsledok celého čísla = addToTwo.apply (5); assertEquals (result, (Integer) 7);
Keď máme metódu, ktorá je z a Funkcia2 typu, môžeme ho ľahko transformovať na štandardnú Javu BiFunkcia použitím a toBiFunction () metóda:
BiFunction biFunc = addTwoNumbers.toBiFunction ();
Podobne existuje a k funkcii() metóda v Funkcia1 typu.
4. Tice
N-tica je vo svete funkčného programovania veľmi dôležitá konštrukcia. Je to písaný kontajner pre hodnoty, kde každá hodnota môže mať iný typ. N-tice sa často používajú ako argumenty funkcií.
Sú tiež veľmi užitočné pri transformácii na prúd udalostí. V službe jOOL máme n-tice, ktoré môžu obsahovať jednu až šestnásť hodnôt poskytnutých Tuple1 až Tuple16 typy:
n-tica (2, 2)
A pre štyri hodnoty:
n-tica (1,2,3,4);
Uvažujme príklad, keď máme postupnosť n-tíc, ktorá niesla 3 hodnoty:
Sekv personDetails = Seq.of (n-tica ("michael", "podobný", 49), n-tica ("jodie", "premenná", 43)); Tuple2 tuple = n-tica („zima“, „leto“); Zoznam result = personDetails .map (t -> t.limit2 (). concat (n-tice)). toList (); assertEquals (result, Arrays.asList (n-tice ("michael", "podobne", "zima", "leto"), n-tice ("jodie", "premenna", "zima", "leto")));
Na n-tice môžeme použiť rôzne druhy transformácií. Najprv nazývame a limit2 () metóda vziať iba dve hodnoty z Tuple3. Potom voláme a concat () metóda na zreťazenie dvoch n-tíc.
Vo výsledku dostaneme hodnoty, ktoré sú a Tuple4 typu.
5. Sekv
The Sekv konštrukt pridáva metódy vyššej úrovne na a Prúd zatiaľ čo často používa svoje metódy pod ním.
5.1. Obsahuje operácie
Nájdeme niekoľko variantov metód kontrolujúcich prítomnosť prvkov v a Sekv. Niektoré z týchto metód používajú anyMatch () metóda z a Prúd trieda:
assertTrue (Seq.of (1, 2, 3, 4). obsahuje (2)); assertTrue (Seq.of (1, 2, 3, 4). obsahuje All (2, 3)); assertTrue (Seq.of (1, 2, 3, 4). obsahuje Any (2, 5));
5.2. Pripojte sa k prevádzke
Keď máme dva streamy a chceme sa k nim pripojiť (podobne ako pri operácii spojenia SQL s dvoma súbormi údajov), pomocou štandardného Prúd triedy nie je veľmi elegantný spôsob, ako to dosiahnuť:
Stream vľavo = Stream.of (1, 2, 4); Stream vpravo = Stream.of (1, 2, 3); Zoznam rightCollected = right.collect (Collectors.toList ()); Zoznam collect = ľavý .filter (rightCollected :: contains) .collect (Collectors.toList ()); assertEquals (collect, Arrays.asList (1, 2));
Musíme pozbierať správny stream do zoznamu, aby sa zabránilo java.lang.IllegalStateException: stream už bol prevádzkovaný alebo uzavretý. Ďalej musíme vykonať operáciu vedľajšieho účinku prístupom k a vpravoZbierané zoznam z a filter metóda. Je to náchylné na chyby a nie je to elegantný spôsob spojenia dvoch súborov údajov.
NašťastieSekv má užitočné metódy na vnútorné, ľavé a pravé spojenie súborov údajov. Tieto metódy skrývajú jeho implementáciu a odhaľujú elegantné API.
Vnútorné spojenie môžeme urobiť pomocou znaku innerJoin () metóda:
assertEquals (Seq.of (1, 2, 4) .innerJoin (Seq.of (1, 2, 3), (a, b) -> a == b) .toList (), Arrays.asList (n-tica (1 , 1), n-tica (2, 2)));
Podľa toho môžeme urobiť pravé a ľavé spojenie:
assertEquals (Seq.of (1, 2, 4) .leftOuterJoin (Seq.of (1, 2, 3), (a, b) -> a == b) .toList (), Arrays.asList (n-tica (1 , 1), n-tica (2, 2), n-tica (4, nulová))); assertEquals (Seq.of (1, 2, 4) .rightOuterJoin (Seq.of (1, 2, 3), (a, b) -> a == b) .toList (), Arrays.asList (n-tica (1 , 1), n-tica (2, 2), n-tica (nulová, 3)));
Existuje dokonca aj crossJoin () metóda umožňujúca kartézske spojenie dvoch súborov údajov:
assertEquals (Seq.of (1, 2) .crossJoin (Seq.of ("A", "B")). toList (), Arrays.asList (n-tice (1, "A"), n-tice (1, "B "), n-tica (2," A "), n-tica (2," B ")));
5.3. Manipulácia a Sekv
Sekv má mnoho užitočných metód na manipuláciu so sekvenciami prvkov. Pozrime sa na niektoré z nich.
Môžeme použiť a cyklus () metóda na opakované prevzatie prvkov zo zdrojovej sekvencie. Vytvorí nekonečný prúd, takže pri zhromažďovaní výsledkov do zoznamu musíme byť opatrní, a preto musíme použiť a limit () metóda na transformáciu nekonečnej sekvencie na konečnú:
assertEquals (Seq.of (1, 2, 3) .cycle (). limit (9) .toList (), Arrays.asList (1, 2, 3, 1, 2, 3, 1, 2, 3));
Povedzme, že chceme duplikovať všetky prvky z jednej postupnosti do druhej postupnosti. The duplikát () metóda robí presne toto:
assertEquals (Seq.of (1, 2, 3) .duplicate (). map ((first, second) -> tuple (first.toList (), second.toList ())), n-tice (Arrays.asList (1, 2, 3), Arrays.asList (1, 2, 3)));
Vracajúci sa typ a duplikát () metóda je n-tica dvoch sekvencií.
Povedzme, že máme postupnosť celých čísel a chceme ju pomocou nejakého predikátu rozdeliť na dve postupnosti. Môžeme použiť a oddiel () metóda:
assertEquals (Seq.of (1, 2, 3, 4). partition (i -> i> 2) .map ((first, second) -> tuple (first.toList (), second.toList ())), n-tica (Arrays.asList (3, 4), Arrays.asList (1, 2)));
5.4. Zoskupovanie prvkov
Zoskupenie prvkov podľa kľúča pomocou Prúd API je ťažkopádne a neintuitívne - pretože ho musíme používať zbierať () metóda s a Collectors.groupingBy zberateľ.
Sekv skryje tento kód za a groupBy () metóda, ktorá sa vráti Mapa takže nie je potrebné používať a zbierať () metóda výslovne:
Mapa expectAfterGroupBy = new HashMap (); expectAfterGroupBy.put (1, Arrays.asList (1, 3)); expectAfterGroupBy.put (0, Arrays.asList (2, 4)); assertEquals (Seq.of (1, 2, 3, 4) .groupBy (i -> i% 2), expectAfterGroupBy);
5.5. Preskakujúce prvky
Povedzme, že máme postupnosť prvkov a chceme preskočiť prvky, zatiaľ čo predikát sa nezhoduje. Keď je predikát splnený, prvky by mali pristáť vo výslednej postupnosti.
Môžeme použiť a skipWhile () metóda na to:
assertEquals (Seq.of (1, 2, 3, 4, 5) .skipWhile (i -> i <3) .toList (), Arrays.asList (3, 4, 5));
Rovnaký výsledok môžeme dosiahnuť pomocou a skipUntil () metóda:
assertEquals (Seq.of (1, 2, 3, 4, 5) .skipUntil (i -> i == 3) .toList (), Arrays.asList (3, 4, 5));
5.6. Sekvencie na zips
Keď spracovávame sekvencie prvkov, často je potrebné ich skomprimovať do jednej sekvencie.
The PSČ() API, ktoré sa dá použiť na spojenie dvoch sekvencií do jednej:
assertEquals (Seq.of (1, 2, 3) .zip (Seq.of ("a", "b", "c")). toList (), Arrays.asList (n-tice (1, "a"), n-tica (2, "b"), n-tica (3, "c")));
Výsledná sekvencia obsahuje n-tice dvoch prvkov.
Keď skomprimujeme dve sekvencie, ale chceme ich skomprimovať konkrétnym spôsobom, môžeme zložiť a BiFunkcia do a PSČ() metóda, ktorá definuje spôsob zipovania prvkov:
assertEquals (Seq.of (1, 2, 3) .zip (Seq.of ("a", "b", "c"), (x, y) -> x + ":" + y) .toList ( ), Arrays.asList ("1: a", "2: b", "3: c"));
Niekedy je užitočné skomprimovať postupnosť pomocou indexu prvkov v tejto sekvencii pomocou indexu zipWithIndex () API:
assertEquals (Seq.of ("a", "b", "c"). zipWithIndex (). toList (), Arrays.asList (tuple ("a", 0L), n-tice ("b", 1L), n-tice ("c", 2L)));
6. Konverzia zaškrtnutých výnimiek na nezačiarknuté
Povedzme, že máme metódu, ktorá vezme reťazec a môže vyvolať kontrolovanú výnimku:
public Integer methodThatThrowsChecked (String arg) hodí Exception {return arg.length (); }
Potom chceme mapovať prvky a Prúd uplatnenie tejto metódy na každý prvok. Neexistuje spôsob, ako zvládnuť túto výnimku vyššie, takže túto výnimku musíme spracovať v a mapa () metóda:
List collect = Stream.of ("a", "b", "c"). Map (elem -> {try {return methodThatThrowsChecked (elem);} catch (Exception e) {e.printStackTrace (); throw new RuntimeException (e);}}). collect (Collectors.toList ()); assertEquals (collect, Arrays.asList (1, 1, 1));
S touto výnimkou toho veľa nemôžeme urobiť kvôli návrhu funkčných rozhraní v Jave, takže v klauzule catch prevádzame skontrolovanú výnimku na nekontrolovanú.
Našťastie v JOOL existuje Nezačiarknuté trieda, ktorá má metódy, ktoré môžu prevádzať skontrolované výnimky na nekontrolované výnimky:
Zoznam collect = Stream.of ("a", "b", "c") .map (Unchecked.function (elem -> methodThatThrowsChecked (elem))) .collect (Collectors.toList ()); assertEquals (collect, Arrays.asList (1, 1, 1));
Zalamujeme hovor na a methodThatThrowsChecked () do Unchecked.function () metóda, ktorá sa stará o prevod výnimiek.
7. Záver
Tento článok ukazuje, ako používať knižnicu jOOL, ktorá pridáva ďalšie užitočné metódy k štandardu Java Prúd API.
Implementáciu všetkých týchto príkladov a útržkov kódu nájdete v projekte GitHub - jedná sa o projekt Maven, takže by malo byť ľahké ho importovať a spustiť tak, ako je.