Filtrere en Java-samling etter en liste

1. Oversikt

Filtrering av en Samling av en Liste er et vanlig forretningslogisk scenario. Det er mange måter å oppnå dette på. Noen kan imidlertid føre til dårlige løsninger hvis de ikke gjøres riktig.

I denne veiledningen, Vi sammenligner noen filtreringsimplementeringer og diskuterer fordelene og ulempene med dem.

2. Bruke en For hver Løkke

Vi begynner med den mest klassiske syntaksen, en for hver løkke.

For dette og alle andre eksempler i denne artikkelen, bruker vi følgende klasse:

offentlig klasse Ansatt {private Heltall ansattNummer; privat strengnavn; privat Heltall avdelingId; // Standardkonstruktør, getters og settere. }

Vi vil også bruke følgende metoder for alle eksempler, for enkelhets skyld:

private List buildEmployeeList () {return Arrays.asList (ny ansatt (1, "Mike", 1), ny ansatt (2, "John", 1), ny ansatt (3, "Mary", 1), ny ansatt ( 4, "Joe", 2), ny ansatt (5, "Nicole", 2), ny ansatt (6, "Alice", 2), ny ansatt (7, "Bob", 3), ny ansatt (8, "Scarlett", 3)); } private List medarbeidernavnFilter () {retur Arrays.asList ("Alice", "Mike", "Bob"); }

For vårt eksempel filtrerer vi den første listen over Ansatte basert på den andre listen med Ansatt navn bare for å finne Ansatte med de spesifikke navnene.

La oss nå se den tradisjonelle tilnærmingen - blar gjennom begge listene på jakt etter treff:

@Test offentlig ugyldighet givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingForEachLoop () {List filteredList = new ArrayList (); Liste originalList = buildEmployeeList (); List nameFilter = ansattNameFilter (); for (Ansatt ansatt: originalList) {for (String name: nameFilter) {if (medarbeider.getName (). tilsvarer (navn)) {filteredList.add (ansatt); // gå i stykker; }}} assertThat (filteredList.size (), er (nameFilter.size ())); }

Dette er en enkel syntaks, men det er ganske ordentlig og faktisk ganske ineffektiv. Enkelt sagt, det det gjentas gjennom det kartesiske produktet av de to settene for å få svaret vårt.

Selv legge til en gå i stykker å avslutte tidlig vil fortsatt gjenta i samme ordre som et kartesisk produkt i gjennomsnitt.

Hvis vi kaller størrelsen på medarbeiderlisten n, deretter nameFilter vil være på bestillingen like stor, og gi oss en O (n2) klassifisering.

3. Bruke Streams og Liste nr inneholder

Vi skal nå omforme den forrige metoden ved å bruke lambdas for å forenkle syntaksen og forbedre lesbarheten. La oss også bruke Liste nr inneholder metoden som lambda filter:

@Test offentlig ugyldighet givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambda () {List filteredList; Liste originalList = buildEmployeeList (); List nameFilter = ansattNameFilter (); filteredList = originalList.stream () .filter (ansatt -> nameFilter.contains (medarbeider.getnavn ())) .collect (Collectors.toList ()); assertThat (filteredList.size (), er (nameFilter.size ())); }

Ved å bruke Stream API, lesbarheten har blitt betydelig forbedret, men koden vår forblir like ineffektiv som vår forrige metode fordi den er fremdeles iterere gjennom det kartesiske produktet internt. Dermed har vi det samme O (n2) klassifisering.

4. Bruke Streams med HashSet

For å forbedre ytelsen, må vi bruke HashSet # inneholder metode. Denne metoden skiller seg fra Liste nr inneholder fordi den utfører en hash-kode oppslag, og gir oss et konstant antall operasjoner:

@Test offentlig ugyldighet givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaAndHashSet () {List filteredList; Liste originalList = buildEmployeeList (); Sett nameFilterSet = ansattNameFilter (). Stream (). Samle (Collectors.toSet ()); filteredList = originalList.stream () .filter (ansatt -> nameFilterSet.contains (medarbeider.getnavn ())) .collect (Collectors.toList ()); assertThat (filteredList.size (), er (nameFilterSet.size ())); }

Ved bruk av HashSet, kodeeffektiviteten vår har blitt betydelig forbedret, men ikke påvirket lesbarheten. Siden HashSet # inneholder kjører i konstant tid, har vi forbedret klassifiseringen til På).

5. Konklusjon

I denne raske opplæringen lærte vi å filtrere en Samling av en Liste av verdier og ulempene ved å bruke det som kan virke som den mest enkle metoden.

Vi må alltid vurdere effektivitet fordi koden vår kan ende opp med å kjøre i enorme datasett, og ytelsesproblemer kan ha katastrofale konsekvenser i slike miljøer.

All kode presentert i denne artikkelen er tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found