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 :)
As mentioned by Jon, you can use Iterables.filter(..) or Collections2.filter(..) and if you don't need a live view you can use ImmutableList.copyOf(Iterables.filter(..)) or Lists.newArrayList( Iterables.filter(..)) and yes ordering will be maintained.
I could use new List(Collection2.filter()) of course, but this way it's not guaranteed that my ordering stays the same.
This isn't true. Collections2.filter() is a lazily-evaluated function - it doesn't actually filter your collection until you start accessing the filtered version. For example, if you iterate over the filtered version, then the filtered elements will pop out of the iterator in the same order as your original collection (minus the ones filtered out, obviously).
Perhaps you were thinking that it does the filtering up front, then dumps the results into an arbitrary, unordered Collection of some form - it doesn't.
So if you use the output of Collections2.filter() as the input to a new list, then your original order will be retained.
Using static imports (and the Lists.newArrayList function), it becomes fairly succinct:
List filteredList = newArrayList(filter(originalList, predicate));
Note that while Collections2.filter will not eagerly iterate over the underlying collection, Lists.newArrayListwill - it will extract all elements of the filtered collection and copy them into a new ArrayList.
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.