Java – Stream szűrése Lambda kifejezésekkel PlatoBlockchain Data Intelligence. Függőleges keresés. Ai.

Java – Stream szűrése Lambda kifejezésekkel

A Java Streams-t egészen a 8-es Java 2014-ban vezették be, annak érdekében, hogy bemutassák a bőbeszédű Java-t a funkcionális programozási paradigmába. A Java Streams számos rugalmas és hatékony funkcionális műveletet tesz lehetővé az egysoros gyűjtési feldolgozás végrehajtásához.

A gyűjtemények bizonyos predikátumokon alapuló szűrése továbbra is az egyik leggyakrabban használt funkcionális művelet, és egy Predicate vagy tömörebben – a Lambda kifejezés.

Ebben a rövid útmutatóban megnézzük, hogyan szűrhet egy Java 8 adatfolyamot Lambda kifejezésekkel.

Streamek szűrése Java nyelven

Általában bármilyen Stream keresztül szűrhető filter() módszer és egy adott predikátum:

Stream filter(Predicate<? super T> predicate)

Az adatfolyam minden eleme az állítmány ellen fut, és hozzáadódik a kimeneti adatfolyamhoz, ha az predikátum visszatér true. Szállíthat a Predicate példa:

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

Vagy egyszerűsítse le Lambda kifejezés megadásával:

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

Vagy akár összecsukja a Lambda kifejezést a módszer hivatkozás:


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

A metódushivatkozásokkal azonban nem adható át argumentum, de metódusokat definiálhat a szűrt objektumban, és könnyen szűrhetővé szabhatja azokat (amíg a metódus nem fogad el argumentumokat, és egy boolean).

Ne feledje, hogy a folyamok nem gyűjtemények - patakok gyűjtemények, és vissza kell gyűjtenie őket bármely gyűjteménybe, például a List, Mapstb., hogy állandóságot adjon nekik. Ezenkívül az összes művelet az adatfolyam elemekkel történik közbülső or terminál:

  • A közbenső műveletek új adatfolyamot adnak vissza az előző művelethez képest változtatásokkal
  • A terminálműveletek egy adattípust adnak vissza, és az adatfolyam feldolgozási folyamatának lezárására szolgálnak

filter() egy közbülső műveletet, és más közbenső műveletekkel kell láncolni, mielőtt az adatfolyam befejeződik. A változtatások (például maguknak az elemeknek vagy a szűrt eredményeknek) a megőrzéséhez hozzá kell rendelnie az eredményül kapott kimeneti folyam egy új referenciaváltozóhoz egy terminálműveleten keresztül.

Jegyzet: Még sok lambda-kifejezés láncolásakor sem ütközhet olvashatósági problémákba megfelelő sortöréssel.

A következő példákban ezzel a könyvlistával fogunk dolgozni:

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

Szűrőgyűjtemény a Stream.filter() segítségével

Szűrjük ezt a könyvgyűjteményt. Bármely predikátum megfelel – tehát például szűrjük meg, hogy mely könyvek 400 oldal felettiek:

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

Ez egy listát eredményez, amely a következőket tartalmazza:

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

Szűréskor egy igazán hasznos módszer a láncoláshoz map(), amely lehetővé teszi az objektumok másik értékre való leképezését. Például leképezhetünk minden könyvet a nevére, és így csak a nevek az állítmánynak megfelelő könyvek közül a filter() hívás:

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

Ez a karakterláncok listáját eredményezi:

[Our Mathematical Universe, Sapiens]

Szűrőgyűjtemény több predikátumra a Stream.filter() segítségével

Általában egynél több feltétel alapján szeretnénk szűrni a gyűjteményeket. Ezt több láncolásával lehet megtenni filter() hívások or egy rövidzárlati predikátumot használva, amely két feltételt ellenőrzi egyetlen helyen filter() hívás.

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

Tekintse meg gyakorlatias, gyakorlati útmutatónkat a Git tanulásához, amely tartalmazza a bevált gyakorlatokat, az iparág által elfogadott szabványokat és a mellékelt csalólapot. Hagyd abba a guglizást a Git parancsokkal, és valójában tanulni meg!

Több kritérium alkalmazása esetén a lambda hívások kissé elhúzódhatnak. Ezen a ponton, ha ezeket önálló predikátumként bontja ki, még egyértelműbb lehet. De melyik megközelítés a gyorsabb?

Egyetlen szűrő összetett állapottal vagy több szűrő?

Ez a hardvertől, a gyűjtemény nagyságától és attól függ, hogy párhuzamos adatfolyamokat használ-e vagy sem. Általánosságban elmondható, hogy egy összetett feltételű szűrő jobban teljesít, mint több egyszerűbb feltételekkel rendelkező szűrő (kis-közepes gyűjtemények), vagy ugyanazon a szinten (nagyon nagy gyűjtemények). Ha a feltételek túl hosszúak – előnyös lehet, ha többre osztja fel őket filter() jobb olvashatóságot kér, mivel a teljesítmény nagyon hasonló.

A legjobb választás mindkettőt kipróbálni, figyelje meg a teljesítményt a céleszköz, és ennek megfelelően módosítsa stratégiáját.

GitHub felhasználó volkodavs szűrési benchmarkot végzett az áteresztőképességi műveletekben, és az eredményeket a következő helyen tárolta „javafilters-benchmarks” adattár. Az eredményeket egy tájékoztató táblázat foglalja össze:

Egyértelműen csökken a hozam nagyobb gyűjteményméret esetén, és mindkét megközelítés nagyjából azonos szinten teljesít. A párhuzamos adatfolyamok jelentős előnyt jelentenek nagyobb gyűjteményméreteknél, de csökkentik a teljesítményt kisebb méreteknél (~10 XNUMX elem alatt). Érdemes megjegyezni, hogy a párhuzamos adatfolyamok sokkal jobban megőrizték átviteli sebességüket, mint a nem párhuzamos folyamok, így lényegesen robusztusabbak a bemenetre.

Időbélyeg:

Még több Stackabus