Java - Filtrer en strøm med Lambda Expressions PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Java – Filtrer en strøm med Lambda-uttrykk

Java-strømmer har blitt introdusert helt tilbake i Java 8 i 2014, i et forsøk på å introdusere detaljert Java til et funksjonelt programmeringsparadigme. Java Streams avslører mange fleksible og kraftige funksjonelle operasjoner for å utføre innsamlingsbehandling i one-liners.

Filtrering av samlinger basert på et predikat er fortsatt en av de mest brukte funksjonelle operasjonene, og kan utføres med en Predicate eller mer konsist – med en Lambda -uttrykk.

I denne korte guiden tar vi en titt på hvordan du kan filtrere en Java 8 Stream med Lambda Expressions.

Filtrering av strømmer i Java

Generelt, evt Stream kan filtreres via filter() metode, og et gitt predikat:

Stream filter(Predicate<? super T> predicate)

Hvert element i strømmen kjøres mot predikatet, og legges til utdatastrømmen hvis predikatet kommer tilbake true. Du kan levere en Predicate forekomst:

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

Eller forenkle det ved å gi et Lambda-uttrykk:

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

Eller til og med kollapse Lambda-uttrykket til et metode referanse:


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

Med metodereferanser kan du ikke sende argumenter, men du kan definere metoder i objektet du filtrerer og skreddersy dem til å være lett filtrerbare (så lenge metoden ikke aksepterer argumenter og returnerer en boolean).

Husk at strømmer er ikke samlinger – de er bekker av samlinger, og du må samle dem tilbake til en hvilken som helst samling, for eksempel en List, Maposv. for å gi dem varighet. I tillegg er alle operasjoner gjort på strømelementer heller mellomliggende or terminal:

  • Mellomoperasjoner returnerer en ny strøm med endringer fra forrige operasjon
  • Terminaloperasjoner returnerer en datatype og er ment å avslutte en pipeline med prosessering på en strøm

filter() er en mellomliggende operasjon, og er ment å kjedes sammen med andre mellomoperasjoner, før strømmen avsluttes. For å opprettholde endringer (som endringer i selve elementene eller filtrerte resultater), må du tilordne de resulterende utgangsstrøm til en ny referansevariabel, gjennom en terminaloperasjon.

OBS: Selv når du lenker mange lambda-uttrykk, kan det hende du ikke får problemer med lesbarheten, med riktige linjeskift.

I de følgende eksemplene skal vi jobbe med denne listen over bøker:

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

Filtrer samling med Stream.filter()

La oss filtrere denne samlingen av bøker. Ethvert predikat går – så la oss for eksempel filtrere etter hvilke bøker som har over 400 sider:

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

Dette resulterer i en liste som inneholder:

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

Ved filtrering er en veldig nyttig metode for å kjede map(), som lar deg kartlegge objekter til en annen verdi. For eksempel kan vi kartlegge hver bok til navnet sitt, og dermed returnere bare navn av bøkene som passer til predikatet fra filter() anrop:

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

Dette resulterer i en liste med strenger:

[Our Mathematical Universe, Sapiens]

Filtersamling på flere predikater med Stream.filter()

Vanligvis ønsker vi å filtrere samlinger etter mer enn ett kriterium. Dette kan gjøres ved å lenke flere filter() samtaler or ved hjelp av et kortslutningspredikat, som sjekker for to tilstander i en enkelt filter() anrop.

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

Sjekk ut vår praktiske, praktiske guide for å lære Git, med beste praksis, bransjeaksepterte standarder og inkludert jukseark. Slutt å google Git-kommandoer og faktisk lære den!

Når du bruker flere kriterier – kan lambda-samtalene bli noe lange. På dette tidspunktet kan det å trekke dem ut som frittstående predikater gi mer klarhet. Men hvilken tilnærming er raskere?

Enkelt filter med kompleks tilstand eller flere filtre?

Det avhenger av maskinvaren din, hvor stor samlingen din er, og om du bruker parallelle strømmer eller ikke. Generelt – ett filter med en kompleks tilstand vil overgå flere filtre med enklere forhold (små til middels samlinger), eller yte på samme nivå (svært store samlinger). Hvis betingelsene dine er for lange – kan du ha nytte av å fordele dem over flere filter() krever forbedret lesbarhet, siden ytelsen er veldig lik.

Det beste valget er å prøve begge, legg merke til ytelsen på målenhet, og juster strategien din deretter.

GitHub-bruker volkodavs gjorde en filtreringsbenchmark i gjennomstrømningsoperasjoner/-er, og var vert for resultatene på "javafilter-benchmarks" oppbevaringssted. Resultatene er oppsummert i en informativ tabell:

Det viser en klar reduksjon i avkastningen ved større samlingsstørrelser, med begge tilnærmingene på omtrent samme nivå. Parallelle strømmer har betydelig fordel ved større samlingsstørrelser, men demper ytelsen ved mindre størrelser (under ~10k elementer). Det er verdt å merke seg at parallelle strømmer opprettholdt sin gjennomstrømning mye bedre enn ikke-parallelle strømmer, noe som gjorde dem betydelig mer robuste for input.

Tidstempel:

Mer fra Stackabuse