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 :)