Есть ли причина?
Lists.transform()
но нет
Lists.filter()
?
Как правильно отфильтровать список? Я мог бы использовать
new ArrayList(Collection2.filter())
конечно, но таким образом не гарантируется, что мой заказ останется прежним, если я правильно понимаю.
List.newArrayList(Iterables.filter(...))
этого следует сказатьLists.newArrayList(Iterables.filter(...))
.Ответы:
Он не был реализован, потому что он предоставил бы опасное большое количество медленных методов, таких как #get (index) в возвращенном представлении списка (вызывая ошибки производительности). И ListIterator тоже было бы сложно реализовать (хотя я отправил патч несколько лет назад, чтобы покрыть это).
Поскольку индексированные методы не могут быть эффективными в представлении отфильтрованного списка, лучше просто использовать отфильтрованный Iterable, у которого их нет.
источник
filter
последовательно означает вид (наряду с поведением, предполагающим) Является ли этоIterables.filter
, иSets.filter
т.д. ТакIterables.filter
комбайнам легко сcopyOf
по любомуImmutableCollection
, я считаю , это хороший дизайн компромисс (против придумывает дополнительными методы и имена, какfilteredCopy
и этажерки , для комбинаций простых утилит).Вы можете использовать
Iterables.filter
, что однозначно поддержит порядок.Обратите внимание, что, создавая новый список, вы будете копировать элементы (конечно, только ссылки) - так что это не будет прямой вид на исходный список. Создание представления было бы довольно сложной задачей - рассмотрим такую ситуацию:
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);
Это должно было бы перебрать весь исходный список, применяя фильтр ко всему. Я полагаю, может потребоваться, чтобы сопоставление предикатов не изменялось за время существования представления, но это было бы не совсем удовлетворительно.
(Это всего лишь предположение, заметьте. Возможно, кто-нибудь из разработчиков Guava объяснит настоящую причину :)
источник
Collections2.filter.iterator
просто звонитIterables.filter
, поэтому результат такой же.Iterables.filter
версию только для ясности.view.size()
то позже в коде :)Это неправда.
Collections2.filter()
это функция с отложенным вычислением - она фактически не фильтрует вашу коллекцию, пока вы не начнете получать доступ к отфильтрованной версии. Например, если вы перебираете отфильтрованную версию, то отфильтрованные элементы будут появляться из итератора в том же порядке, что и исходная коллекция (за вычетом отфильтрованных, очевидно).Возможно, вы думали, что он выполняет фильтрацию заранее, а затем выгружает результаты в произвольную, неупорядоченную коллекцию некоторой формы - это не так.
Поэтому, если вы используете вывод в
Collections2.filter()
качестве входных данных для нового списка, то ваш исходный порядок будет сохранен.Используя статический импорт (и
Lists.newArrayList
функцию), он становится довольно лаконичным:Обратите внимание , что в то время
Collections2.filter
не охотно итерация по основной коллекции,Lists.newArrayList
будет - он будет извлекать все элементы отфильтрованной коллекции и скопировать их в новыйArrayList
.источник
List filteredList = newArrayList(filter(originalList, new Predicate<T>() { @Override public boolean apply(T input) { return (...); } }));
или т.е.List filteredList = newArrayList(filter(originalList, Predicates.notNull()));
Как упоминал Джон, вы можете использовать
Iterables.filter(..)
или,Collections2.filter(..)
и если вам не нужен просмотр в реальном времени, вы можете использоватьImmutableList.copyOf(Iterables.filter(..))
или,Lists.newArrayList( Iterables.filter(..))
и да, порядок будет сохранен.Если вас действительно интересует, зачем нужна часть, вы можете посетить https://github.com/google/guava/issues/505 для получения дополнительных сведений.
источник
Подводя итог тому, что сказали другие, вы можете легко создать общую оболочку для фильтрации списков:
public static <T> List<T> filter(Iterable<T> userLists, Predicate<T> predicate) { return Lists.newArrayList(Iterables.filter(userLists, predicate)); }
источник