Czy jest jakiś powód
Lists.transform()
ale nie
Lists.filter()
?
Jak poprawnie filtrować listę? mógłbym użyć
new ArrayList(Collection2.filter())
oczywiście, ale w ten sposób nie ma gwarancji, że moje zamówienie pozostanie niezmienione, jeśli dobrze rozumiem.
List.newArrayList(Iterables.filter(...))
, powinno byćLists.newArrayList(Iterables.filter(...))
.Odpowiedzi:
Nie został zaimplementowany, ponieważ ujawniłby niebezpieczną dużą liczbę powolnych metod, takich jak #get (indeks) w zwróconym widoku listy (wywołując błędy wydajności). A ListIterator również byłby trudny do wdrożenia (chociaż przesłałem łatkę lata temu, aby to pokryć).
Ponieważ metody indeksowane nie mogą być wydajne w przefiltrowanym widoku listy, lepiej jest po prostu skorzystać z filtrowanej iterowalnej, która ich nie ma.
źródło
filter
konsekwentnie oznacza view (wraz z zachowaniem sugerujący) czy toIterables.filter
,Sets.filter
itd PonieważIterables.filter
kombajnów łatwocopyOf
na dowolnyImmutableCollection
, uważam ten kompromis dobry projekt (vs wymyślanie dodatkowych metod i nazw, jakfilteredCopy
i etażerka , dla kombinacji prostych narzędzi).Możesz skorzystać
Iterables.filter
, co na pewno utrzyma porządek.Zwróć uwagę, że konstruując nową listę, będziesz kopiować elementy (oczywiście tylko odniesienia) - więc nie będzie to podgląd na żywo na oryginalną listę. Tworzenie widoku byłoby dość trudne - rozważ taką sytuację:
Predicate<StringBuilder> predicate = /* predicate returning whether the builder is empty */ List<StringBuilder> builders = Lists.newArrayList(); List<StringBuilder> view = Lists.filter(builders, predicate); for (int i = 0; i < 10000; i++) { builders.add(new StringBuilder()); } builders.get(8000).append("bar"); StringBuilder firstNonEmpty = view.get(0);
To wymagałoby iteracji po całej oryginalnej liście, stosując filtr do wszystkiego. Przypuszczam, że mogłoby to wymagać, aby dopasowywanie predykatów nie zmieniało się przez cały czas istnienia widoku, ale nie byłoby to całkowicie satysfakcjonujące.
(To tylko zgadywanie, pamiętajcie. Może któryś z opiekunów guawy włączy się z prawdziwym powodem :)
źródło
Collections2.filter.iterator
tylko dzwoniIterables.filter
, więc wynik jest taki sam.Iterables.filter
wersji tylko dla przejrzystości.view.size()
gdzieś później w kodzie :)To nieprawda.
Collections2.filter()
jest funkcją ocenianą leniwie - w rzeczywistości nie filtruje kolekcji, dopóki nie zaczniesz uzyskiwać dostępu do przefiltrowanej wersji. Na przykład, jeśli iterujesz po przefiltrowanej wersji, przefiltrowane elementy wyskakują z iteratora w tej samej kolejności, co oryginalna kolekcja (oczywiście bez odfiltrowanych).Być może myślałeś, że filtruje z góry, a następnie zrzuca wyniki do dowolnego, nieuporządkowanego zbioru jakiejś formy - tak nie jest.
Jeśli więc użyjesz danych wyjściowych
Collections2.filter()
jako danych wejściowych do nowej listy, oryginalna kolejność zostanie zachowana.Używając importu statycznego (i
Lists.newArrayList
funkcji), staje się dość zwięzły:Zauważ, że while
Collections2.filter
nie będzie chętnie iterował po kolekcji bazowej,Lists.newArrayList
będzie - wyodrębni wszystkie elementy przefiltrowanej kolekcji i skopiuje je do nowejArrayList
.źródło
List filteredList = newArrayList(filter(originalList, new Predicate<T>() { @Override public boolean apply(T input) { return (...); } }));
lub tj.List filteredList = newArrayList(filter(originalList, Predicates.notNull()));
Jak wspomniał Jon, możesz użyć
Iterables.filter(..)
lub,Collections2.filter(..)
a jeśli nie potrzebujesz podglądu na żywo, możesz użyćImmutableList.copyOf(Iterables.filter(..))
lubLists.newArrayList( Iterables.filter(..))
i tak, porządkowanie zostanie zachowane.Jeśli naprawdę interesuje Cię dlaczego warto, możesz odwiedzić https://github.com/google/guava/issues/505, aby uzyskać więcej informacji.
źródło
Podsumowując to, co powiedzieli inni, możesz łatwo utworzyć ogólne opakowanie do filtrowania list:
public static <T> List<T> filter(Iterable<T> userLists, Predicate<T> predicate) { return Lists.newArrayList(Iterables.filter(userLists, predicate)); }
źródło