Chcę filtrować na java.util.Collection
podstawie predykatu.
java
collections
filter
Kevin Wong
źródło
źródło
persons.removeIf(p -> p.getAge() <= 16);
Zakładając, że używasz Java 1.5 i nie możesz dodawać kolekcji Google , zrobiłbym coś bardzo podobnego do tego, co zrobili chłopaki Google. To niewielka zmiana w komentarzach Jona.
Najpierw dodaj ten interfejs do swojej bazy kodów.
Jego realizatorzy mogą odpowiedzieć, gdy określony predykat jest prawdziwy określonego typu. Np. Jeśli
T
byłyUser
iAuthorizedUserPredicate<User>
implementujeIPredicate<T>
, toAuthorizedUserPredicate#apply
zwraca, czy przekazaneUser
jest autoryzowany.W niektórych klasach użytkowych można powiedzieć
Zakładając, że masz do dyspozycji powyższe, może być
Jeśli problem dotyczy wydajności kontroli liniowej, może chciałbym mieć obiekt domeny z kolekcją docelową. Obiekt domeny, który ma kolekcję docelową, miałby logikę filtrowania dla metod inicjujących, dodających i ustawiających kolekcję docelową.
AKTUALIZACJA:
W klasie użytkowej (powiedzmy Predicate) dodałem metodę select z opcją wartości domyślnej, gdy predykat nie zwraca oczekiwanej wartości, a także właściwość statyczną dla parametrów, które będą używane w nowym IPredicate.
Poniższy przykład szuka brakujących obiektów między kolekcjami:
Poniższy przykład wyszukuje instancję w kolekcji i zwraca pierwszy element kolekcji jako wartość domyślną, gdy instancja nie zostanie znaleziona:
AKTUALIZACJA (po wydaniu Java 8):
Minęło kilka lat, odkąd (Alan) po raz pierwszy opublikowałem tę odpowiedź, i nadal nie mogę uwierzyć, że zbieram punkty SO za tę odpowiedź. W każdym razie, teraz, gdy Java 8 wprowadziła zamknięcia języka, moja odpowiedź byłaby teraz znacznie inna i prostsza. W Javie 8 nie ma potrzeby posiadania odrębnej statycznej klasy narzędzi. Więc jeśli chcesz znaleźć pierwszy element, który pasuje do twojego predykatu.
JDK 8 API dla optionals ma możliwość
get()
,isPresent()
,orElse(defaultUser)
,orElseGet(userSupplier)
iorElseThrow(exceptionSupplier)
, a także inne funkcje „” monadycznego takie jakmap
,flatMap
ifilter
.Jeśli chcesz po prostu zebrać wszystkich użytkowników, którzy pasują do predykatu, użyj przycisku,
Collectors
aby zakończyć strumień w żądanej kolekcji.Zobacz tutaj po więcej przykładów, w jaki sposób Java 8 strumieni pracy.
źródło
val authorized = for (user <- users if user.isAuthorized) yield user
Użyj CollectionUtils.filter (Collection, Predicate) , z Apache Commons.
źródło
„Najlepszy” sposób to zbyt szerokie żądanie. Czy to jest „najkrótsze”? "Najszybszy"? "Czytelny"? Filtrować w miejscu lub w innej kolekcji?
Najprostszym (ale niezbyt czytelnym) sposobem jest iteracja i użycie metody Iterator.remove ():
Teraz, aby uczynić go bardziej czytelnym, możesz zawinąć go w metodę narzędzia. Następnie wymyśl interfejs IPredicate, utwórz anonimową implementację tego interfejsu i zrób coś takiego:
gdzie filterInPlace () iteruje kolekcję i wywołuje Predicate.keepIt (), aby dowiedzieć się, czy instancja ma być przechowywana w kolekcji.
Naprawdę nie widzę uzasadnienia dla wprowadzenia biblioteki innej firmy tylko do tego zadania.
źródło
stream()
funkcja, ale nie wszyscy mogą bawić się najnowszymi zabawkami: PZastanów się nad kolekcjami Google, aby uzyskać zaktualizowaną strukturę kolekcji, która obsługuje generyczne.
AKTUALIZACJA : Biblioteka kolekcji Google jest teraz przestarzała. Zamiast tego powinieneś użyć najnowszej wersji Guava . Nadal ma te same rozszerzenia w strukturze kolekcji, w tym mechanizm filtrowania oparty na predykacie.
źródło
Poczekaj na Javę 8:
źródło
personList.removeIf(p -> p.age < 30);
Mniej gadatliwy. Słyszałem też o tym, jak zacząć wdrażać api, które akceptują i zwracająStream
s zamiastCollection
s, ponieważStream
są bardzo przydatne i szybkie, ale przechodzenie do / z nich jest powolne.Od wczesnej wersji Java 8 możesz wypróbować coś takiego:
Na przykład, jeśli masz listę liczb całkowitych i chcesz przefiltrować liczby o wartości> 10, a następnie wydrukować te liczby na konsoli, możesz zrobić coś takiego:
źródło
Dorzucę RxJava w pierścieniu, który jest również dostępny na Androida . RxJava nie zawsze może być najlepszą opcją, ale da ci większą elastyczność, jeśli chcesz dodać więcej transformacji w swojej kolekcji lub obsłużyć błędy podczas filtrowania.
Wynik:
Więcej informacji na temat RxJava
filter
można znaleźć tutaj .źródło
Ustawić:
Użycie:
źródło
Co powiesz na prostą i prostą Javę
Prosty, czytelny i łatwy (i działa na Androidzie!) Ale jeśli używasz Java 8, możesz to zrobić w jednym słodkim wierszu:
Zauważ, że toList () jest importowany statycznie
źródło
Czy na pewno chcesz filtrować samą kolekcję, a nie iterator?
zobacz org.apache.commons.collections.iterators.FilterIterator
lub używając wersji 4 apache commons org.apache.commons.collections4.iterators.FilterIterator
źródło
Przyjrzyjmy się, jak filtrować wbudowaną listę JDK i MutableList przy użyciu kolekcji Eclipse .
Jeśli chcesz filtrować liczby mniejsze niż 3, możesz oczekiwać następujących wyników.
Oto, w jaki sposób można filtrować, używając lambda Java 8 jako
Predicate
.Oto, w jaki sposób możesz filtrować za pomocą anonimowej klasy wewnętrznej jako
Predicate
.Oto kilka alternatyw dla filtrowania list JDK i MutableLists kolekcji Eclipse Kolekcje przy użyciu fabryki predykatów .
Oto wersja, która nie przydziela obiektu do predykatu, używając zamiast tego fabryki Predicates2 z
selectWith
metodą, która wymagaPredicate2
.Czasami chcesz filtrować według stanu ujemnego. W tym celu istnieje specjalna metoda w kolekcji Eclipse
reject
.Metoda
partition
zwróci dwie kolekcje, zawierające elementy wybrane przez i odrzucone przezPredicate
.Uwaga: jestem osobą odpowiedzialną za kolekcje Eclipse.
źródło
removeIf
na liście lub zestawie dla prymitywów?Z ForEach DSL możesz pisać
Biorąc pod uwagę zbiór [The, quick, brown, lis, jumps, over, the, leniwy, pies] skutkuje to [szybkim, brązowym, jumps, over, leniwym], tj. Wszystkie łańcuchy dłuższe niż trzy znaki.
Wszystkie style iteracji obsługiwane przez ForEach DSL są
AllSatisfy
AnySatisfy
Collect
Counnt
CutPieces
Detect
GroupedBy
IndexOf
InjectInto
Reject
Select
Aby uzyskać więcej informacji, zobacz https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach
źródło
Metoda Collections2.filter (Collection, Predicate) w bibliotece Google Guava robi dokładnie to, czego szukasz.
źródło
Ponieważ Java 9
Collectors.filtering
jest włączona:Dlatego filtrowanie powinno być:
Przykład:
źródło
To, w połączeniu z brakiem prawdziwych zamknięć, jest moim największym problemem dla Javy. Szczerze mówiąc, większość wyżej wymienionych metod jest dość łatwa do odczytania i NAPRAWDĘ wydajna; jednak po spędzeniu czasu z .Net, Erlang itp. zintegrowane na poziomie języka zrozumienie listy sprawia, że wszystko jest o wiele czystsze. Bez dodatków na poziomie językowym Java nie może być tak czysta, jak wiele innych języków w tym obszarze.
Jeśli wydajność jest ogromnym problemem, kolekcje Google to droga (lub napisz własne proste narzędzie predykcyjne). Składnia Lambdaj jest bardziej czytelna dla niektórych osób, ale nie jest tak wydajna.
A potem jest biblioteka, którą napisałem. Zignoruję wszelkie pytania dotyczące jego skuteczności (tak, to takie złe) ...... Tak, wiem, że jest oparte na wyraźnej refleksji i nie, nie używam go, ale działa:
LUB
źródło
JFilter http://code.google.com/p/jfilter/ najlepiej pasuje do twoich wymagań.
JFilter to prosta i wysokowydajna biblioteka open source do przeszukiwania kolekcji ziaren Java.
Kluczowe cechy
źródło
Napisałem rozszerzoną klasę Iterable, która obsługuje stosowanie algorytmów funkcjonalnych bez kopiowania zawartości kolekcji.
Stosowanie:
Powyższy kod zostanie faktycznie wykonany
źródło
Użyj Collection Query Engine (CQEngine) . To zdecydowanie najszybszy sposób na zrobienie tego.
Zobacz także: Jak przeszukiwać kolekcje obiektów w Javie (podobne do kryteriów / SQL)?
źródło
Oto kilka naprawdę świetnych odpowiedzi. Ja chciałbym, aby cienkie były tak proste i czytelne, jak to możliwe:
źródło
Proste rozwiązanie wcześniejsze niż Java8:
Niestety to rozwiązanie nie jest w pełni ogólne, generując listę, a nie typ danej kolekcji. Także wprowadzanie bibliotek lub pisanie funkcji, które zawijają ten kod, wydaje mi się przesadą, chyba że warunek jest złożony, ale wtedy możesz napisać funkcję dla tego warunku.
źródło
https://code.google.com/p/joquery/
Obsługuje różne możliwości,
Biorąc pod uwagę kolekcję,
typu
Filtr
Java 7
Java 8
Również,
Sortowanie (dostępne również dla Java 7)
Grupowanie (dostępne również dla Java 7)
Połączenia (dostępne również dla Java 7)
Dany,
Można dołączyć,
Wyrażenia
źródło
Moja odpowiedź opiera się na tej odpowiedzi Kevina Wonga, tutaj jako jednowierszowej, wykorzystującej
CollectionUtils
od wiosny i wyrażenia lambda Java 8 .Jest to tak zwięzłe i czytelne, jak każda alternatywa, którą widziałem (bez korzystania z bibliotek aspektowych)
Spring CollectionUtils jest dostępny od wersji wiosennej 4.0.2. ZWOLNIJ, i pamiętaj, że potrzebujesz JDK 1.8 i poziomu językowego 8+.
źródło
Używając
java 8
,lambda expression
możesz zrobić to po prostu jak w poniższym przykładzie:gdzie dla każdej kolekcji
product
wewnętrznejmyProducts
, jeśliprod.price>10
, to dodaj ten produkt do nowej filtrowanej listy.źródło
Musiałem przefiltrować listę w zależności od wartości już obecnych na liście. Na przykład usuń wszystkie następujące wartości, które są mniejsze niż bieżąca wartość. {2 5 3 4 7 5} -> {2 5 7}. Lub na przykład, aby usunąć wszystkie duplikaty {3 5 4 2 3 5 6} -> {3 5 4 2 6}.
To będzie używane w ten sposób.
źródło
Z Guava:
źródło
W Javie 8 możesz bezpośrednio użyć tej metody filtrowania, a następnie to zrobić.
źródło