我想根据谓词筛选java.util.Collection。
当前回答
这一点,再加上缺少真正的闭包,是我对Java最大的不满。 老实说,上面提到的大多数方法都很容易阅读,而且真的很有效;然而,在学习了。net、Erlang等之后……在语言级别集成的列表理解使一切变得更加清晰。如果没有在语言级别上的添加,Java就不能像这个领域的许多其他语言一样干净。
如果性能非常重要,那么可以使用谷歌集合(或者编写自己的简单谓词实用程序)。Lambdaj语法对某些人来说可读性更好,但效率不高。
然后有一个我写的库。我将忽略任何关于其效率的问题(是的,它很糟糕)......是的,我知道它清楚地基于反射,不,我实际上没有使用它,但它确实工作:
LinkedList<Person> list = ......
LinkedList<Person> filtered =
Query.from(list).where(Condition.ensure("age", Op.GTE, 21));
OR
LinkedList<Person> list = ....
LinkedList<Person> filtered = Query.from(list).where("x => x.age >= 21");
其他回答
在Java 8中,您可以直接使用此过滤器方法,然后执行此操作。
List<String> lines = Arrays.asList("java", "pramod", "example");
List<String> result = lines.stream()
.filter(line -> !"pramod".equals(line))
.collect(Collectors.toList());
result.forEach(System.out::println);
让我们看看如何使用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的提交者。
使用来自Apache Commons的CollectionUtils.filter(Collection,Predicate)。
这里有一些非常棒的答案。对我来说,我想让事情尽可能简单易懂:
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();
}
}
}
}
}
考虑使用支持泛型的更新的Collections框架谷歌Collections。
更新:谷歌集合库现在已弃用。你应该使用最新发布的番石榴。它仍然具有对集合框架的所有相同扩展,包括基于谓词进行筛选的机制。
推荐文章
- 在log4j中,在记录日志之前检查isDebugEnabled是否能提高性能?
- 没有JAXB生成的@XmlRootElement
- Java中对象的内存消耗是多少?
- 获取Spring应用程序背景信息
- 为什么在Java中使用静态嵌套接口?
- @Mock, @MockBean和Mockito.mock()的区别
- JDK 8中的PermGen消除
- 如何将CharSequence转换为字符串?
- 在Java中初始化一个long
- Java的数组indexOf在哪里?
- 同一个键下的多个值
- 使用JSTL检查集合大小
- Java“虚拟机”vs. Python“解释器”的说法?
- 获取操作系统级别的系统信息
- 如何通过SFTP从服务器检索文件?