我想根据谓词筛选java.util.Collection。


当前回答

您确定要筛选Collection本身,而不是迭代器吗?

看到org.apache.commons.collections.iterators.FilterIterator

或者使用apache commons的第四版org.apache.commons.collections4.iterators.FilterIterator

其他回答

从Java 8的早期发行版开始,你可以尝试这样做:

Collection<T> collection = ...;
Stream<T> stream = collection.stream().filter(...);

例如,如果你有一个整数列表,你想过滤> 10的数字,然后将这些数字打印到控制台,你可以这样做:

List<Integer> numbers = Arrays.asList(12, 74, 5, 8, 16);
numbers.stream().filter(n -> n > 10).forEach(System.out::println);

这一点,再加上缺少真正的闭包,是我对Java最大的不满。 老实说,上面提到的大多数方法都很容易阅读,而且真的很有效;然而,在学习了。net、Erlang等之后……在语言级别集成的列表理解使一切变得更加清晰。如果没有在语言级别上的添加,Java就不能像这个领域的许多其他语言一样干净。

如果性能非常重要,那么可以使用谷歌集合(或者编写自己的简单谓词实用程序)。Lambdaj语法对某些人来说可读性更好,但效率不高。

然后有一个我写的库。我将忽略任何关于其效率的问题(是的,它很糟糕)......是的,我知道它清楚地基于反射,不,我实际上没有使用它,但它确实工作:

LinkedList<Person> list = ......
LinkedList<Person> filtered = 
           Query.from(list).where(Condition.ensure("age", Op.GTE, 21));

OR

LinkedList<Person> list = ....
LinkedList<Person> filtered = Query.from(list).where("x => x.age >= 21");

谷歌的Guava库中的Collections2.filter(Collection,Predicate)方法正是您所寻找的。

等待Java 8:

List<Person> olderThan30 = 
  //Create a Stream from the personList
  personList.stream().
  //filter the element to select only those with age >= 30
  filter(p -> p.age >= 30).
  //put those filtered elements into a new List.
  collect(Collectors.toList());

我将把RxJava加入其中,它在Android上也可用。RxJava可能并不总是最好的选择,但如果您希望在集合上添加更多转换或在过滤时处理错误,RxJava将为您提供更大的灵活性。

Observable.from(Arrays.asList(1, 2, 3, 4, 5))
    .filter(new Func1<Integer, Boolean>() {
        public Boolean call(Integer i) {
            return i % 2 != 0;
        }
    })
    .subscribe(new Action1<Integer>() {
        public void call(Integer i) {
            System.out.println(i);
        }
    });

输出:

1
3
5

更多关于RxJava过滤器的细节可以在这里找到。