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


当前回答

这里有一些非常棒的答案。对我来说,我想让事情尽可能简单易懂:

public abstract class AbstractFilter<T> {

    /**
     * Method that returns whether an item is to be included or not.
     * @param item an item from the given collection.
     * @return true if this item is to be included in the collection, false in case it has to be removed.
     */
    protected abstract boolean excludeItem(T item);

    public void filter(Collection<T> collection) {
        if (CollectionUtils.isNotEmpty(collection)) {
            Iterator<T> iterator = collection.iterator();
            while (iterator.hasNext()) {
                if (excludeItem(iterator.next())) {
                    iterator.remove();
                }
            }
        }
    }
}

其他回答

Java 8(2014)在一行代码中使用流和lambdas解决了这个问题:

List<Person> beerDrinkers = persons.stream()
    .filter(p -> p.getAge() > 16).collect(Collectors.toList());

这是一个教程。

使用Collection#removeIf在适当的地方修改集合。(注意:在这种情况下,谓词将删除满足谓词的对象):

persons.removeIf(p -> p.getAge() <= 16);

Lambdaj允许在不编写循环或内部类的情况下过滤集合:

List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
    greaterThan(16)));

你能想象出更有可读性的东西吗?

免责声明:我是lambdaj的贡献者

我的回答建立在Kevin Wong的基础上,这里是一个使用spring中的CollectionUtils和Java 8 lambda表达式的一行程序。

CollectionUtils.filter(list, p -> ((Person) p).getAge() > 16);

这是我见过的最简洁易读的方法(不使用基于方面的库)。

Spring CollectionUtils可从Spring版本4.0.2获得。请记住,您需要JDK 1.8和语言级别8+。

java8之前的简单解决方案:

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

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

JFilter http://code.google.com/p/jfilter/最适合您的需求。

JFilter是一个简单、高性能的开源库,用于查询Java bean集合。

关键特性

Support of collection (java.util.Collection, java.util.Map and Array) properties. Support of collection inside collection of any depth. Support of inner queries. Support of parameterized queries. Can filter 1 million records in few 100 ms. Filter ( query) is given in simple json format, it is like Mangodb queries. Following are some examples. { "id":{"$le":"10"} where object id property is less than equals to 10. { "id": {"$in":["0", "100"]}} where object id property is 0 or 100. {"lineItems":{"lineAmount":"1"}} where lineItems collection property of parameterized type has lineAmount equals to 1. { "$and":[{"id": "0"}, {"billingAddress":{"city":"DEL"}}]} where id property is 0 and billingAddress.city property is DEL. {"lineItems":{"taxes":{ "key":{"code":"GST"}, "value":{"$gt": "1.01"}}}} where lineItems collection property of parameterized type which has taxes map type property of parameteriszed type has code equals to GST value greater than 1.01. {'$or':[{'code':'10'},{'skus': {'$and':[{'price':{'$in':['20', '40']}}, {'code':'RedApple'}]}}]} Select all products where product code is 10 or sku price in 20 and 40 and sku code is "RedApple".

设置:

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();
  }
});