Filtriranje Java zbirke po popisu
1. Pregled
Filtriranje a Kolekcija od strane a Popis je uobičajeni scenarij poslovne logike. Puno je načina da se to postigne. Međutim, neka mogu dovesti do rješenja s lošim učinkom ako se ne učine pravilno.
U ovom vodiču, usporedit ćemo neke implementacije filtriranja i razgovarati o njihovim prednostima i nedostacima.
2. Korištenje a Za svakoga Petlja
Započet ćemo s najklasičnijom sintaksom, petljom za svaku.
Za ovaj i sve ostale primjere u ovom članku koristit ćemo sljedeću klasu:
javni razred zaposlenik {private Integer workerNumber; privatni naziv niza; privatni Integer odjelId; // Standardni konstruktor, geteri i postavljači. }
Za sve primjere koristit ćemo i sljedeće metode radi jednostavnosti:
privatni popis buildEfficieeList () {return Arrays.asList (novi zaposlenik (1, "Mike", 1), novi zaposlenik (2, "John", 1), novi zaposlenik (3, "Mary", 1), novi zaposlenik ( 4, "Joe", 2), novi zaposlenik (5, "Nicole", 2), novi zaposlenik (6, "Alice", 2), novi zaposlenik (7, "Bob", 3), novi zaposlenik (8, "Scarlett", 3)); } privatni popis workerNameFilter () {return Arrays.asList ("Alice", "Mike", "Bob"); }
Za naš primjer filtrirat ćemo prvi popis Zaposlenici na temelju drugog popisa sa Zaposlenik imena za pronalaženje samo Zaposlenici s tim određenim imenima.
Pogledajmo sada tradicionalni pristup - pregledavajući oba popisa tražeći podudaranja:
@Test javna praznina givenEfficieeList_andNameFilterList_thenObtainFilteredEfficieeList_usingForEachLoop () {Popis filteredList = new ArrayList (); Popis originalList = buildEfficieeList (); Ime popisaFilter = workerNameFilter (); za (Zaposleni zaposlenik: originalList) {za (Naziv niza: nameFilter) {if (zaposlenik.getName (). je jednako (ime)) {filteredList.add (zaposlenik); // pauza; }}} assertThat (filteredList.size (), je (nameFilter.size ())); }
Ovo je jednostavna sintaksa, ali prilično je opširna i zapravo prilično neučinkovita. Jednostavno rečeno, to ponavlja kroz kartezijanski proizvod dvaju skupova kako bismo dobili naš odgovor.
Čak i dodavanje a pauza za rani izlazak i dalje će se ponavljati istim redoslijedom kao i kartezijski proizvod u prosječnom slučaju.
Ako zovemo veličinu popisa zaposlenika n, zatim nameFilter bit će na narudžbi jednako veliko, dajući nam an O (n2) klasifikacija.
3. Korištenje Streamova i Lista # sadrži
Sada ćemo refaktorizirati prethodnu metodu pomoću lambda-a radi pojednostavljenja sintakse i poboljšanja čitljivosti. Koristimo i Lista # sadrži metoda kao lambda filter:
@Test javna praznina givenEfficieeList_andNameFilterList_thenObtainFilteredEfficieeList_usingLambda () {Popis filteredList; Popis originalList = buildEfficieeList (); Ime popisaFilter = workerNameFilter (); filteredList = originalList.stream () .filter (zaposlenik -> nameFilter.contens (worker.getName ())) .collect (Collectors.toList ()); assertThat (filteredList.size (), je (nameFilter.size ())); }
Korištenjem Stream API, čitljivost je znatno poboljšana, ali naš kôd ostaje jednako neučinkovit kao i naša prethodna metoda, jer je još uvijek interno prolazeći kroz kartezijanski proizvod. Dakle, imamo isto O (n2) klasifikacija.
4. Korištenje streama s HashSet
Da bismo poboljšali performanse, moramo koristiti HashSet # sadrži metoda. Ova se metoda razlikuje od Lista # sadrži jer izvodi a hash kod pretraživanja, dajući nam konstantni broj operacija:
@Test javna praznina givenEfficieeList_andNameFilterList_thenObtainFilteredEfficieeList_usingLambdaAndHashSet () {Popis filteredList; Popis originalList = buildEfficieeList (); Postavite nameFilterSet = workerNameFilter (). Stream (). Collect (Collectors.toSet ()); filteredList = originalList.stream () .filter (zaposlenik -> nameFilterSet.contens (worker.getName ())) .collect (Collectors.toList ()); assertThat (filteredList.size (), je (nameFilterSet.size ())); }
Pomoću HashSet, naša se učinkovitost koda znatno poboljšala, a da pritom nije utjecala na čitljivost. Od HashSet # sadrži radi u stalnom vremenu, poboljšali smo klasifikaciju na Na).
5. Zaključak
U ovom smo brzom vodiču naučili kako filtrirati a Kolekcija od strane a Popis vrijednosti i nedostaci korištenja onoga što se može činiti najjednostavnijom metodom.
Uvijek moramo razmotriti učinkovitost, jer bi naš kôd mogao završiti s ogromnim skupovima podataka, a problemi s izvedbom u takvim bi okruženjima mogli imati katastrofalne posljedice.
Sav kôd predstavljen u ovom članku dostupan je na GitHubu.