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


当前回答

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

其他回答

您可以使用ForEach DSL编写

import static ch.akuhn.util.query.Query.select;
import static ch.akuhn.util.query.Query.$result;
import ch.akuhn.util.query.Select;

Collection<String> collection = ...

for (Select<String> each : select(collection)) {
    each.yield = each.value.length() > 3;
}

Collection<String> result = $result();

给定一个集合[The, quick, brown, fox, jumping, over, The, lazy, dog],结果是[quick, brown, jumping, over, lazy],即所有字符串都长于三个字符。

ForEach DSL支持的所有迭代样式都是

AllSatisfy AnySatisfy 收集 Counnt CutPieces 检测 GroupedBy IndexOf InjectInto 拒绝 选择

更多详情请参考https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach

我将把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过滤器的细节可以在这里找到。

番石榴:

Collection<Integer> collection = Lists.newArrayList(1, 2, 3, 4, 5);

Iterators.removeIf(collection.iterator(), new Predicate<Integer>() {
    @Override
    public boolean apply(Integer i) {
        return i % 2 == 0;
    }
});

System.out.println(collection); // Prints 1, 3, 5

使用集合查询引擎(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();
  }
});