Java - Filtrirajte tok z lambda izrazi PlatoBlockchain Data Intelligence. Navpično iskanje. Ai.

Java – filtrirajte tok z lambda izrazi

Tokovi Java so bili predstavljeni že v Javi 8 leta 2014, da bi podrobno Javo uvedli v paradigmo funkcionalnega programiranja. Java Streams razkrijejo številne prilagodljive in zmogljive funkcionalne operacije za izvajanje obdelave zbirk v eni vrstici.

Filtriranje zbirk na podlagi nekega predikata ostaja ena najpogosteje uporabljenih funkcionalnih operacij in jo je mogoče izvesti z Predicate ali bolj jedrnato – z a Lambda izraz.

V tem kratkem vodniku si bomo ogledali, kako lahko filtrirate tok Java 8 z lambda izrazi.

Filtriranje tokov v Javi

Na splošno, kateri koli Stream je mogoče filtrirati prek filter() metoda in dani predikat:

Stream filter(Predicate<? super T> predicate)

Vsak element v toku se izvaja proti predikatu in se doda izhodnemu toku, če predikat vrne true. Lahko priskrbite a Predicate primer:

Predicate contains = s -> s.contains("_deprecated");
List results = stream.filter(contains).collect(Collectors.toList());

Ali pa ga poenostavite tako, da zagotovite lambda izraz:

List results = stream.filter(s -> s.contains("_deprecated"))
                             .collect(Collectors.toList());

Ali celo strnite lambda izraz v a referenca metode:


List results = stream.filter(String::isEmpty)
                             .collect(Collectors.toList());

Pri referencah metod ne morete posredovati argumentov, lahko pa definirate metode v predmetu, ki ga filtrirate, in jih prilagodite tako, da jih je mogoče zlahka filtrirati (dokler metoda ne sprejme argumentov in vrne boolean).

Ne pozabite, da tokovi niso zbirke – to so potoki zbirk, in jih boste morali zbrati nazaj v katero koli zbirko, kot je a List, Map, itd., da bi jim zagotovili trajnost. Poleg tega vse operacije, izvedene na elementih toka srednja or terminal:

  • Vmesne operacije vrnejo nov tok s spremembami prejšnje operacije
  • Operacije terminala vrnejo podatkovni tip in so namenjene zaključku cevovoda obdelave v toku

filter() je srednja operacijo in naj bi bila povezana z drugimi vmesnimi operacijami, preden se tok zaključi. Če želite obdržati kakršne koli spremembe (kot so spremembe samih elementov ali filtrirani rezultati), boste morali dodeliti nastale izhodni tok na novo referenčno spremenljivko prek terminalske operacije.

Opomba: Tudi pri veriženju številnih lambda izrazov morda ne boste naleteli na težave z berljivostjo z ustreznimi prelomi vrstic.

V naslednjih primerih bomo delali s tem seznamom knjig:

Book book1 = new Book("001", "Our Mathematical Universe", "Max Tegmark", 432, 2014);
Book book2 = new Book("002", "Life 3.0", "Max Tegmark", 280, 2017);
Book book3 = new Book("003", "Sapiens", "Yuval Noah Harari", 443, 2011);
        
List books = Arrays.asList(book1, book2, book3);

Filtriraj zbirko s Stream.filter()

Filtrirajmo to zbirko knjig. Velja kateri koli predikat – zato na primer filtrirajmo, katere knjige imajo več kot 400 strani:

List results = books.stream()
                          .filter(b -> b.getPageNumber() > 400)
                          .collect(Collectors.toList());

Posledica tega je seznam, ki vsebuje:

[
Book{id='001', name='Our Mathematical Universe', author='Max Tegmark', pageNumber=432, publishedYear=2014}, 
Book{id='003', name='Sapiens', author='Yuval Noah Harari', pageNumber=443, publishedYear=2011}
]

Pri filtriranju je zelo uporaben način veriženja map(), ki vam omogoča preslikavo predmetov v drugo vrednost. Na primer, vsako knjigo lahko preslikamo v njeno ime in tako vrnemo samo Imena knjig, ki ustrezajo predikatu iz filter() klic:

List results = books.stream()
                            .filter(b -> b.getPageNumber() > 400)
                            .map(Book::getName)
                            .collect(Collectors.toList());

Posledica tega je seznam nizov:

[Our Mathematical Universe, Sapiens]

Filtrirajte zbirko na več predikatih s Stream.filter()

Običajno želimo filtrirati zbirke po več kot enem kriteriju. To je mogoče storiti z veriženjem več filter() klici or z uporabo predikata kratkega stika, ki preveri dva pogoja v enem filter() klic.

 List results = books.stream()
                    .filter(b -> b.getPageNumber() > 400 && b.getName().length() > 10)
                    .collect(Collectors.toList());
                    


 List results2 = books.stream()
                    .filter(b -> b.getPageNumber() > 400)
                    .filter(b -> b.getName().length() > 10)
                    .collect(Collectors.toList());

Oglejte si naš praktični, praktični vodnik za učenje Gita z najboljšimi praksami, standardi, sprejetimi v panogi, in priloženo goljufijo. Nehajte Googlati ukaze Git in pravzaprav naučiti it!

Pri uporabi več meril lahko klici lambda postanejo nekoliko dolgotrajni. Na tej točki bi lahko njihovo ekstrahiranje kot samostojne predikate ponudilo več jasnosti. Vendar, kateri pristop je hitrejši?

En filter s kompleksnim pogojem ali več filtrov?

Odvisno je od vaše strojne opreme, kako velika je vaša zbirka in ali uporabljate vzporedne tokove ali ne. Na splošno bo en filter s kompleksnim pogojem boljši od več filtrov s preprostejšimi pogoji (majhne do srednje velike zbirke) ali deluje na enaki ravni (zelo velike zbirke). Če so vaši pogoji predolgi – vam bo morda koristilo, če jih razdelite na več filter() poziva, za izboljšano berljivost, saj je zmogljivost zelo podobna.

Najboljša izbira je, da poskusite oboje, upoštevajte učinkovitost na ciljna napravain ustrezno prilagodite svojo strategijo.

Uporabnik GitHub volkodavs izvedla merilo uspešnosti filtriranja v prepustnih operacijah in gostila rezultate na “javafilters-benchmarks” repozitorij. Rezultati so povzeti v informativni tabeli:

Kaže očitno zmanjševanje donosov pri večjih velikostih zbiranja, pri čemer sta oba pristopa dosegla približno enako raven. Vzporedni tokovi znatno koristijo pri večjih velikostih zbirk, vendar zmanjšajo zmogljivost pri manjših velikostih (pod ~10k elementov). Treba je omeniti, da so vzporedni tokovi ohranili svojo prepustnost veliko bolje kot nevzporedni tokovi, zaradi česar so bistveno bolj robustni za vnos.

Časovni žig:

Več od Stackabuse