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


当前回答

使用集合查询引擎(CQEngine)。这是目前为止最快的方法。

请参见:如何在Java中查询对象集合(Criteria/SQL-like)?

其他回答

设置:

public interface Predicate<T> {
  public boolean filter(T t);
}

void filterCollection(Collection<T> col, Predicate<T> predicate) {
  for (Iterator i = col.iterator(); i.hasNext();) {
    T obj = i.next();
    if (predicate.filter(obj)) {
      i.remove();
    }
  }
}

的用法:

List<MyObject> myList = ...;
filterCollection(myList, new Predicate<MyObject>() {
  public boolean filter(MyObject obj) {
    return obj.shouldFilter();
  }
});

等待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());

java8之前的简单解决方案:

ArrayList<Item> filtered = new ArrayList<Item>(); 
for (Item item : items) if (condition(item)) filtered.add(item);

不幸的是,这个解决方案不是完全通用的,它输出的是一个列表,而不是给定集合的类型。此外,在我看来,引入库或编写函数来包装这段代码似乎有些过分,除非条件很复杂,但随后可以为该条件编写函数。

您确定要筛选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);