Guawa: dlaczego nie ma List.funkcja filter ()?

Czy Jest jakiś powód

Lists.transform()

Ale nie

Lists.filter()

?

Jak poprawnie filtrować listę? I could use

new ArrayList(Collection2.filter())

Oczywiście, ale w ten sposób nie ma gwarancji, że moje zamówienie pozostanie takie samo, jeśli dobrze rozumiem.

Author: Xaerxess, 2011-12-10

5 answers

Nie został zaimplementowany, ponieważ ujawniłby niebezpieczną dużą liczbę powolnych metod, takich jak #get (index) w zwróconym widoku listy (zapraszając błędy wydajności). A ListIterator też byłby bolączką do implementacji (choć przed laty nadesłałem patch, aby to pokryć).

Ponieważ metody indeksowane nie mogą być wydajne w widoku filtrowanej listy, lepiej użyć filtrowanej Iterowalnej, która ich nie ma.

 55
Author: Dimitris Andreou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-07 16:59:38

Możesz użyć Iterables.filter, który z pewnością zachowa porządek.

Zauważ, że konstruując nową listę, będziesz kopiować elementy (oczywiście tylko odniesienia) - więc nie będzie to aktywny widok na oryginalną listę. Tworzenie widoku byłoby dość trudne-rozważ tę 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 musiałoby iterować na całej oryginalnej liście, stosując filtr do wszystkiego. Przypuszczam, że może to wymagać, aby dopasowanie predykatu nie zmieniło się w ciągu żywotność widoku, ale to nie byłoby-całkowicie-zadowalające.

To tylko zgadywanie. Może jeden z opiekunów Guava będzie chip z prawdziwy powód:)
 37
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-16 21:02:53

Mógłbym użyć new List(Collection2.filter()) oczywiście, ale w ten sposób nie ma gwarancji, że moje zamówienie pozostanie takie samo.

To nieprawda. {[2] } jest leniwie ocenianą funkcją - w rzeczywistości nie filtruje Twojej kolekcji, dopóki nie zaczniesz uzyskiwać dostępu do filtrowanej wersji. Na przykład, jeśli wykonasz iterację nad przefiltrowaną wersją, To przefiltrowane elementy wyskakują z iteratora w takiej samej kolejności jak oryginalna kolekcja (oczywiście bez przefiltrowanych elementów).

Być może nie jest to jednak możliwe, ponieważ nie jest to możliwe w przypadku, gdy nie jest to możliwe.]}

Więc jeśli użyjesz wyjścia Collections2.filter() jako wejścia do nowej listy, wtedy oryginalny porządek zostanie zachowany.

Używając importu statycznego (i funkcji Lists.newArrayList), staje się dość zwięzły:

List filteredList = newArrayList(filter(originalList, predicate));

Zauważ, że podczas gdy Collections2.filter nie będzie, Lists.newArrayList will - będzie Wyodrębnij wszystkie elementy przefiltrowanej kolekcji i skopiuj je do nowej ArrayList.

 28
Author: skaffman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-10 21:52:04

Jak wspomniał Jon, możesz użyć Iterables.filter(..) LUB Collections2.filter(..), a jeśli nie potrzebujesz widoku na żywo, możesz użyć ImmutableList.copyOf(Iterables.filter(..)) lub Lists.newArrayList( Iterables.filter(..)) i kolejność tak zostanie zachowana.

Jeśli naprawdę interesuje CięDlaczego część, możesz odwiedzić https://github.com/google/guava/issues/505 po więcej szczegółów.

 12
Author: Premraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-04 10:20:46

Podsumowując to, co powiedzieli inni, możesz łatwo utworzyć ogólny wrapper do filtrowania List:

public static <T> List<T> filter(Iterable<T> userLists, Predicate<T> predicate) {
    return Lists.newArrayList(Iterables.filter(userLists, predicate));
}
 6
Author: Holger Brandl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-16 09:24:34