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


当前回答

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

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

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

其他回答

您可以使用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

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

设置:

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

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

从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);