Articles

Filtrere En Java-Samling etter En Liste

Oversikt

Filtrere En Samling etter En Liste er et vanlig forretningslogikkscenario. Det er mange måter å oppnå dette på. Noen kan imidlertid føre til underpresterende løsninger hvis det ikke gjøres riktig.

i denne opplæringen, vil vi sammenligne noen filtrering implementeringer og diskutere sine fordeler og ulemper.

Ved Å Bruke En For-Hver Sløyfe

begynner vi med den mest klassiske syntaksen, en for – hver sløyfe.

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

public class Employee { private Integer employeeNumber; private String name; private Integer departmentId; //Standard constructor, getters and setters.}

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

private List<Employee> buildEmployeeList() { return Arrays.asList( new Employee(1, "Mike", 1), new Employee(2, "John", 1), new Employee(3, "Mary", 1), new Employee(4, "Joe", 2), new Employee(5, "Nicole", 2), new Employee(6, "Alice", 2), new Employee(7, "Bob", 3), new Employee(8, "Scarlett", 3));}private List<String> employeeNameFilter() { return Arrays.asList("Alice", "Mike", "Bob");}

for vårt eksempel filtrerer vi den første Listen Over Ansatte basert på Den Andre listen Med Ansattnavn for å finne Bare De Ansatte med de spesifikke navn.

Nå, la oss se den tradisjonelle tilnærmingen-looping gjennom begge lister på jakt etter kamper:

@Testpublic void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingForEachLoop() { List<Employee> filteredList = new ArrayList<>(); List<Employee> originalList = buildEmployeeList(); List<String> nameFilter = employeeNameFilter(); for (Employee employee : originalList) { for (String name : nameFilter) { if (employee.getName().equals(name)) { filteredList.add(employee); // break; } } } assertThat(filteredList.size(), is(nameFilter.size()));}

dette er en enkel syntaks, men det er ganske verbose, og faktisk ganske ineffektivt. Enkelt sagt, det itererer gjennom Det Kartesiske produktet av de to settene for å få svaret vårt.

selv å legge til en pause for å avslutte tidlig vil fortsatt iterere på samme rekkefølge som Et Kartesisk produkt i gjennomsnittlig tilfelle.

hvis vi kaller størrelsen på ansattlisten n, vil nameFilter være på bestillingen like stor, noe som gir Oss En o(n2) klassifisering.

Bruke Strømmer og Liste # inneholder

Vi vil nå refactor den forrige metoden ved å bruke lambdas for å forenkle syntaks og forbedre lesbarheten. La Oss også bruke List # contains-metoden som lambda-filteret:

@Testpublic void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambda() { List<Employee> filteredList; List<Employee> originalList = buildEmployeeList(); List<String> nameFilter = employeeNameFilter(); filteredList = originalList.stream() .filter(employee -> nameFilter.contains(employee.getName())) .collect(Collectors.toList()); assertThat(filteredList.size(), is(nameFilter.size()));}

ved å bruke Stream API har lesbarheten blitt kraftig forbedret, men koden vår forblir like ineffektiv som vår forrige metode fordi den fortsatt itererer gjennom Det Kartesiske produktet internt. Dermed har Vi samme o (n2) klassifisering.

Bruke Strømmer med HashSet

for å forbedre ytelsen må vi bruke HashSet#inneholder metoden. Denne metoden er forskjellig fra List#contains fordi Den utfører et hash-kodeoppslag, noe som gir oss et konstant antall operasjoner:

@Testpublic void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaAndHashSet() { List<Employee> filteredList; List<Employee> originalList = buildEmployeeList(); Set<String> nameFilterSet = employeeNameFilter().stream().collect(Collectors.toSet()); filteredList = originalList.stream() .filter(employee -> nameFilterSet.contains(employee.getName())) .collect(Collectors.toList()); assertThat(filteredList.size(), is(nameFilterSet.size()));}

Ved Å bruke HashSet har kodens effektivitet blitt betydelig forbedret mens den ikke påvirker lesbarheten. Siden HashSet # inneholder løp i konstant tid, har vi forbedret klassifiseringen Til O (n).

Konklusjon

i denne raske opplæringen lærte vi å filtrere En Samling med en liste over verdier og ulempene ved å bruke det som kan virke som den enkleste metoden.Vi må alltid vurdere effektivitet fordi koden vår kan ende opp med å kjøre i store datasett, og ytelsesproblemer kan ha katastrofale konsekvenser i slike miljøer.

all kode som presenteres i denne artikkelen er tilgjengelig over På GitHub.

Kom i gang Med Våren 5 Og Våren Boot 2, Gjennom Lær Våren kurset:

>> SJEKK UT KURSET