Java - Filtrer en stream med Lambda Expressions PlatoBlockchain Data Intelligence. Lodret søgning. Ai.

Java – Filtrer en stream med Lambda-udtryk

Java Streams er blevet introduceret helt tilbage i Java 8 i 2014 i et forsøg på at introducere verbose Java til et funktionelt programmeringsparadigme. Java Streams afslører mange fleksible og kraftfulde funktionelle operationer til at udføre indsamlingsbehandling i one-liners.

Filtrering af samlinger baseret på et prædikat er fortsat en af ​​de mest almindeligt anvendte funktionelle operationer og kan udføres med en Predicate eller mere kortfattet – med en Lambda udtryk.

I denne korte guide tager vi et kig på, hvordan du kan filtrere en Java 8 Stream med Lambda Expressions.

Filtrering af streams i Java

Generelt kan evt Stream kan filtreres via filter() metode og et givet prædikat:

Stream filter(Predicate<? super T> predicate)

Hvert element i strømmen køres mod prædikatet og føjes til outputstrømmen, hvis prædikatet vender tilbage true. Du kan levere en Predicate eksempel:

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

Eller forenkle det ved at angive et Lambda-udtryk:

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

Eller endda kollapse Lambda-udtrykket til et metodehenvisning:


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

Med metodereferencer kan du ikke sende argumenter, men du kan definere metoder i det objekt, du filtrerer, og skræddersy dem, så de let kan filtreres (så længe metoden ikke accepterer argumenter og returnerer en boolean).

Husk, at streams er ikke samlinger – de er vandløb af samlinger, og du bliver nødt til at samle dem tilbage i enhver samling som f.eks List, Maposv. for at give dem varighed. Derudover udføres alle operationer på stream-elementer mellemliggende or terminal:

  • Mellemliggende operationer returnerer en ny strøm med ændringer fra den tidligere operation
  • Terminaloperationer returnerer en datatype og er beregnet til at afslutte en pipeline af behandling på en strøm

filter() er en mellemliggende drift, og er beregnet til at blive kædet sammen med andre mellemliggende operationer, før strømmen afsluttes. For at fortsætte ændringer (såsom ændringer af selve elementerne eller filtrerede resultater), skal du tildele den resulterende outputstrøm til en ny referencevariabel gennem en terminaloperation.

Bemærk: Selv når du kæder mange lambda-udtryk, løber du muligvis ikke ind i læsbarhedsproblemer med korrekte linjeskift.

I de følgende eksempler arbejder vi med denne liste over bøger:

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

Lad os filtrere denne samling af bøger. Ethvert prædikat gælder – så lad os f.eks. filtrere efter, hvilke bøger der har over 400 sider:

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

Dette resulterer i en liste, der indeholder:

[
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 rigtig nyttig metode til at kæde map(), som lader dig kortlægge objekter til en anden værdi. For eksempel kan vi kortlægge hver bog til dens navn og dermed kun returnere navne af de bøger, der passer til prædikatet fra filter() opkald:

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

Dette resulterer i en liste over strenge:

[Our Mathematical Universe, Sapiens]

Filterindsamling på flere prædikater med Stream.filter()

Normalt vil vi gerne filtrere samlinger efter mere end ét kriterium. Dette kan gøres ved at kæde flere filter() opkald or ved hjælp af et kortslutningsprædikat, som cheks for to tilstande i en enkelt filter() opkald.

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

Tjek vores praktiske, praktiske guide til at lære Git, med bedste praksis, brancheaccepterede standarder og inkluderet snydeark. Stop med at google Git-kommandoer og faktisk lærer det!

Når man bruger flere kriterier – kan lambda-opkaldene blive noget lange. På dette tidspunkt kan det give mere klarhed at udtrække dem som selvstændige prædikater. Men hvilken tilgang er hurtigere?

Enkelt filter med kompleks tilstand eller flere filtre?

Det afhænger af din hardware, hvor stor din samling er, og om du bruger parallelle streams eller ej. Generelt – ét filter med en kompleks tilstand vil udkonkurrere flere filtre med enklere forhold (små til mellemstore samlinger) eller yde på samme niveau (meget store samlinger). Hvis dine betingelser er for lange - kan du med fordel fordele dem over flere filter() opfordrer til den forbedrede læsbarhed, da ydeevnen er meget ens.

Det bedste valg er at prøve begge dele, bemærk ydeevnen på målenhed, og juster din strategi i overensstemmelse hermed.

GitHub bruger volkodavs lavede et filtreringsbenchmark i gennemløbsoperationer/er og hostede resultaterne på "javafilter-benchmarks" depot. Resultaterne er opsummeret i en informativ tabel:

Det viser et klart fald i afkast ved større samlingsstørrelser, hvor begge tilgange præsterer omkring samme niveau. Parallelle streams gavner betydeligt ved større samlingsstørrelser, men dæmper ydeevnen ved mindre størrelser (under ~10k elementer). Det er værd at bemærke, at parallelle strømme bevarede deres gennemløb meget bedre end ikke-parallelle strømme, hvilket gjorde dem betydeligt mere robuste over for input.

Tidsstempel:

Mere fra Stablemisbrug