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


当前回答

让我们看看如何使用Eclipse Collections筛选内置JDK List和MutableList。

List<Integer> jdkList = Arrays.asList(1, 2, 3, 4, 5);
MutableList<Integer> ecList = Lists.mutable.with(1, 2, 3, 4, 5);

如果希望过滤小于3的数字,则会得到以下输出。

List<Integer> selected = Lists.mutable.with(1, 2);
List<Integer> rejected = Lists.mutable.with(3, 4, 5);

下面介绍如何使用Java 8 lambda作为Predicate进行筛选。

Assert.assertEquals(selected, Iterate.select(jdkList, each -> each < 3));
Assert.assertEquals(rejected, Iterate.reject(jdkList, each -> each < 3));

Assert.assertEquals(selected, ecList.select(each -> each < 3));
Assert.assertEquals(rejected, ecList.reject(each -> each < 3));

下面介绍如何使用匿名内部类作为Predicate进行筛选。

Predicate<Integer> lessThan3 = new Predicate<Integer>()
{
    public boolean accept(Integer each)
    {
        return each < 3;
    }
};

Assert.assertEquals(selected, Iterate.select(jdkList, lessThan3));
Assert.assertEquals(selected, ecList.select(lessThan3));

下面是一些使用Predicates工厂过滤JDK列表和Eclipse Collections mutabllists的替代方案。

Assert.assertEquals(selected, Iterate.select(jdkList, Predicates.lessThan(3)));
Assert.assertEquals(selected, ecList.select(Predicates.lessThan(3)));

下面是一个不为谓词分配对象的版本,而是使用Predicates2工厂,并使用selectWith方法接受Predicate2。

Assert.assertEquals(
    selected, ecList.selectWith(Predicates2.<Integer>lessThan(), 3));

有时你想过滤一个消极的条件。在Eclipse Collections中有一个特殊的方法叫做reject。

Assert.assertEquals(rejected, Iterate.reject(jdkList, lessThan3));
Assert.assertEquals(rejected, ecList.reject(lessThan3));

方法分区将返回两个集合,包含Predicate选择和拒绝的元素。

PartitionIterable<Integer> jdkPartitioned = Iterate.partition(jdkList, lessThan3);
Assert.assertEquals(selected, jdkPartitioned.getSelected());
Assert.assertEquals(rejected, jdkPartitioned.getRejected());

PartitionList<Integer> ecPartitioned = gscList.partition(lessThan3);
Assert.assertEquals(selected, ecPartitioned.getSelected());
Assert.assertEquals(rejected, ecPartitioned.getRejected());

注意:我是Eclipse Collections的提交者。

其他回答

设置:

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

在我的情况下,我正在寻找与特定字段空排除列表。 这可以用for循环来完成,并填充没有空地址的对象的临时列表。 但是多亏了Java 8流

List<Person> personsList = persons.stream()
.filter(p -> p.getAdrress() != null).collect(Collectors.toList());

#java #集合#集合#java8 #流

使用来自Apache Commons的CollectionUtils.filter(Collection,Predicate)。

我写了一个扩展的Iterable类,它支持在不复制集合内容的情况下应用函数式算法。

用法:

List<Integer> myList = new ArrayList<Integer>(){ 1, 2, 3, 4, 5 }

Iterable<Integer> filtered = Iterable.wrap(myList).select(new Predicate1<Integer>()
{
    public Boolean call(Integer n) throws FunctionalException
    {
        return n % 2 == 0;
    }
})

for( int n : filtered )
{
    System.out.println(n);
}

上面的代码将实际执行

for( int n : myList )
{
    if( n % 2 == 0 ) 
    {
        System.out.println(n);
    }
}

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