Java - Suodata virta Lambda-lausekkeilla PlatoBlockchain Data Intelligence. Pystysuuntainen haku. Ai.

Java – Suodata virta Lambda-lausekkeilla

Java Streams on otettu käyttöön aina Java 8:ssa vuonna 2014, jotta monisanainen Java otettiin käyttöön toiminnallisen ohjelmoinnin paradigmaan. Java Streams paljastaa monia joustavia ja tehokkaita toiminnallisia operaatioita keräyskäsittelyn suorittamiseksi yhden rivin kautta.

Joihinkin predikaattiin perustuvien kokoelmien suodatus on edelleen yksi yleisimmin käytetyistä toiminnallisista toiminnoista, ja se voidaan suorittaa Predicate tai tiiviimmin - a Lambda Expression.

Tässä lyhyessä oppaassa tarkastellaan, kuinka voit suodattaa Java 8 -virran Lambda-lausekkeilla.

Virtojen suodatus Javassa

Yleensä mikä tahansa Stream voidaan suodattaa kautta filter() menetelmä ja tietty predikaatti:

Stream filter(Predicate<? super T> predicate)

Jokainen virran elementti ajetaan predikaattia vastaan ​​ja lisätään tulosvirtaan, jos predikaatti palauttaa true. Voit toimittaa a Predicate ilmentymä:

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

Tai yksinkertaista sitä antamalla Lambda-lauseke:

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

Tai jopa tiivistää Lambda-lausekkeen a menetelmäviittaus:


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

Metodiviittauksilla et voi välittää argumentteja, mutta voit määrittää menetelmiä suodattavassa objektissa ja räätälöidä ne helposti suodatettaviksi (kunhan menetelmä ei hyväksy argumentteja ja palauttaa boolean).

Muista, että streamit eivät ole kokoelmia – ne ovat puroja kokoelmista, ja sinun on kerättävä ne takaisin mihin tahansa kokoelmaan, kuten a List, Mapjne. antaakseen niille pysyvyyttä. Lisäksi kaikki toiminnot tehdään stream-elementeillä väli- or terminaali:

  • Välioperaatiot palauttavat uuden virran, jossa on muutoksia edelliseen operaatioon
  • Päätetoiminnot palauttavat tietotyypin ja niiden on tarkoitus lopettaa virran käsittelyputki

filter() On väli- ja se on tarkoitettu ketjutettavaksi muiden välitoimintojen kanssa ennen kuin virta lopetetaan. Jos haluat säilyttää muutokset (kuten muutokset itse elementteihin tai suodatetut tulokset), sinun on määritettävä tuloksena lähtövirta uuteen referenssimuuttujaan päätetoiminnon kautta.

Huomautus: Vaikka ketjutat monia lambda-lausekkeita, et ehkä törmää luettavuusongelmiin oikeilla rivinvaihdoilla.

Seuraavissa esimerkeissä työskentelemme tämän kirjaluettelon kanssa:

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);

Suodata kokoelma Stream.filter()

Suodatetaan tämä kirjakokoelma. Mikä tahansa predikaatti käy – joten suodatetaan esimerkiksi sen mukaan, millä kirjoilla on yli 400 sivua:

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

Tämä johtaa luetteloon, joka sisältää:

[
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}
]

Suodattaessa todella hyödyllinen tapa ketjuttaa on map(), jonka avulla voit kartoittaa objektit toiseen arvoon. Voimme esimerkiksi yhdistää jokaisen kirjan sen nimeen ja siten palauttaa vain kirjan nimet kirjoista, jotka sopivat predikaattiin filter() puhelu:

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

Tämä johtaa luetteloon merkkijonoista:

[Our Mathematical Universe, Sapiens]

Suodatinkokoelma useille predikaateille Stream.filter()

Yleensä haluamme suodattaa kokoelmia useamman kuin yhden ehdon mukaan. Tämä voidaan tehdä ketjuttamalla useita filter() puhelut or käyttämällä oikosulkupredikaattia, joka tarkistaa kaksi ehtoa yhdessä filter() puhelu.

 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());

Tutustu käytännönläheiseen, käytännölliseen Gitin oppimisoppaaseemme, jossa on parhaat käytännöt, alan hyväksymät standardit ja mukana tuleva huijauslehti. Lopeta Git-komentojen googlailu ja oikeastaan oppia se!

Useita kriteerejä käytettäessä lambda-kutsut voivat venyä jonkin verran pitkiksi. Tässä vaiheessa niiden purkaminen itsenäisinä predikaatteina saattaa tarjota enemmän selkeyttä. Kumpi lähestymistapa on kuitenkin nopeampi?

Yksi suodatin monimutkaisilla olosuhteilla vai useita suodattimia?

Se riippuu laitteistostasi, kuinka suuri kokoelmasi on ja käytätkö rinnakkaisia ​​streameja vai et. Yleisesti ottaen yksi monimutkaisen ehdon sisältävä suodatin tehostaa useita suodattimia yksinkertaisemmilla ehdoilla (pienistä keskikokoisiin kokoelmat) tai toimii samalla tasolla (erittäin suuret kokoelmat). Jos ehdot ovat liian pitkät – saatat hyötyä niiden jakamisesta useille filter() vaatii parempaa luettavuutta, koska suorituskyky on hyvin samanlainen.

Paras valinta on kokeilla molempia, huomioi suorituskyvyn kohdelaiteja muokkaa strategiaasi sen mukaisesti.

GitHub-käyttäjä volkodavs teki suodatusvertailun suoritustehooperaatioissa/s ja isännöi tulokset "javafilters-benchmarks" arkisto. Tulokset on koottu informatiiviseen taulukkoon:

Se osoittaa selkeän tuoton vähenemisen suuremmilla kokoelmakooilla, kun molemmat lähestymistavat toimivat suunnilleen samalla tasolla. Rinnakkaisvirrat hyötyvät merkittävästi suuremmissa kokoelmakokoissa, mutta heikentävät suorituskykyä pienemmillä kooilla (alle 10 XNUMX elementtiä). On syytä huomata, että rinnakkaiset virrat säilyttivät suoritustehonsa paljon paremmin kuin ei-rinnakkaiset virrat, mikä teki niistä huomattavasti kestävämpiä syötettäessä.

Aikaleima:

Lisää aiheesta Stackabus