Guava: Why is there no Lists.filter() function?
Is there a reason there's
Lists.transform()
but no
Lists.filter()
?
How do I filter a list correctly? I could use
new ArrayList(Collection2.filter())
of course, but this way it's not guaranteed that my ordering stays the same, if I understand correctly.
Solution 1:
It wasn't implemented because it would expose a perilous large number of slow methods, such as #get(index) on the returned List view (inviting performance bugs). And ListIterator would be a pain to implement as well (though I submitted a patch years ago to cover that).
Since indexed methods can't be efficient in the filtered List view, it's better to just go with a filtered Iterable, which doesn't have them.
Solution 2:
You can use Iterables.filter
, which will definitely maintain ordering.
Note that by constructing a new list, you'll be copying the elements (just references, of course) - so it won't be a live view onto the original list. Creating a view would be pretty tricky - consider this situation:
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);
That would have to iterate over the whole original list, applying the filter to everything. I suppose it could require that the predicate matching didn't change over the lifetime of the view, but that would be not-entirely-satisfactory.
(This is just guessing, mind you. Maybe one of the Guava maintainers will chip in with the real reason :)