我想根据谓词筛选java.util.Collection。
当前回答
从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);
其他回答
在我的情况下,我正在寻找与特定字段空排除列表。 这可以用for循环来完成,并填充没有空地址的对象的临时列表。 但是多亏了Java 8流
List<Person> personsList = persons.stream()
.filter(p -> p.getAdrress() != null).collect(Collectors.toList());
#java #集合#集合#java8 #流
使用集合查询引擎(CQEngine)。这是目前为止最快的方法。
请参见:如何在Java中查询对象集合(Criteria/SQL-like)?
假设您使用的是Java 1.5,并且不能添加谷歌集合,我将做一些非常类似于谷歌人员所做的事情。这与乔恩的评论略有不同。
首先将该接口添加到代码库中。
public interface IPredicate<T> { boolean apply(T type); }
它的实现者可以回答特定类型的某个谓词何时为真。例如,如果T是User, AuthorizedUserPredicate<User>实现IPredicate<T>,那么AuthorizedUserPredicate#apply返回传入的User是否被授权。
然后在一些实用类中,你可以说
public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
Collection<T> result = new ArrayList<T>();
for (T element: target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}
所以,假设你有以上可能的用途
Predicate<User> isAuthorized = new Predicate<User>() {
public boolean apply(User user) {
// binds a boolean method in User to a reference
return user.isAuthorized();
}
};
// allUsers is a Collection<User>
Collection<User> authorizedUsers = filter(allUsers, isAuthorized);
如果关心线性检查的性能,那么我可能希望有一个具有目标集合的域对象。具有目标集合的域对象将具有用于初始化、添加和设置目标集合的方法的过滤逻辑。
更新:
在实用程序类(假设是Predicate)中,我添加了一个select方法,其中有一个在谓词不返回预期值时用于默认值的选项,还有一个用于在新IPredicate中使用的参数的静态属性。
public class Predicate {
public static Object predicateParams;
public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
Collection<T> result = new ArrayList<T>();
for (T element : target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}
public static <T> T select(Collection<T> target, IPredicate<T> predicate) {
T result = null;
for (T element : target) {
if (!predicate.apply(element))
continue;
result = element;
break;
}
return result;
}
public static <T> T select(Collection<T> target, IPredicate<T> predicate, T defaultValue) {
T result = defaultValue;
for (T element : target) {
if (!predicate.apply(element))
continue;
result = element;
break;
}
return result;
}
}
下面的例子查找集合之间缺失的对象:
List<MyTypeA> missingObjects = (List<MyTypeA>) Predicate.filter(myCollectionOfA,
new IPredicate<MyTypeA>() {
public boolean apply(MyTypeA objectOfA) {
Predicate.predicateParams = objectOfA.getName();
return Predicate.select(myCollectionB, new IPredicate<MyTypeB>() {
public boolean apply(MyTypeB objectOfB) {
return objectOfB.getName().equals(Predicate.predicateParams.toString());
}
}) == null;
}
});
下面的示例在集合中查找实例,如果找不到实例,则返回集合的第一个元素作为默认值:
MyType myObject = Predicate.select(collectionOfMyType, new IPredicate<MyType>() {
public boolean apply(MyType objectOfMyType) {
return objectOfMyType.isDefault();
}}, collectionOfMyType.get(0));
更新(Java 8发布后):
自从我(艾伦)第一次发布这个答案已经有好几年了,我仍然不敢相信我的这个答案能获得SO分。无论如何,现在Java 8已经在语言中引入了闭包,我的答案将会有很大的不同,而且更简单。在Java 8中,不需要单独的静态实用程序类。如果你想找到匹配谓词的第一个元素。
final UserService userService = ... // perhaps injected IoC
final Optional<UserModel> userOption = userCollection.stream().filter(u -> {
boolean isAuthorized = userService.isAuthorized(u);
return isAuthorized;
}).findFirst();
JDK 8 API的可选功能有get(), isPresent(), orElse(defaultUser), orElseGet(userSupplier)和orElseThrow(exceptionSupplier),以及其他“单体”函数,如map, flatMap和filter。
如果您只想收集与谓词匹配的所有用户,那么使用collector终止所需集合中的流。
final UserService userService = ... // perhaps injected IoC
final List<UserModel> userOption = userCollection.stream().filter(u -> {
boolean isAuthorized = userService.isAuthorized(u);
return isAuthorized;
}).collect(Collectors.toList());
有关Java 8流如何工作的更多示例,请参见这里。
Java集合流的一个替代(更轻量级的)选择是Ocl.java库,它使用vanilla集合和lambdas: https://github.com/eclipse/agileuml/blob/master/Ocl.java
例如,对数组列表中的单词进行简单的筛选和求和 可能是:
ArrayList<Word> sel = Ocl.selectSequence(words,
w -> w.pos.equals("NN"));
int total = Ocl.sumint(Ocl.collectSequence(sel,
w -> w.text.length()));
Where Word有字符串pos;字符串文本;属性。效率似乎与流选项相似,例如,在两个版本中,10000个单词在大约50毫秒内处理。
Python、Swift等都有等效的OCL库。基本上,Java集合流重新发明了OCL操作——>select, ->collect等,这些操作自1998年以来就存在于OCL中。
我的回答建立在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+。
推荐文章
- 如何检查JSON键是否存在?
- 为什么MongoDB Java驱动在条件中使用随机数生成器?
- 即使从未抛出异常,使用try-catch块的代价是否昂贵?
- 什么时候我们应该使用观察者和可观察对象?
- Java中的split()方法对点(.)不起作用。
- Eclipse调试器总是阻塞在ThreadPoolExecutor上,没有任何明显的异常,为什么?
- Java生成两个给定值之间的随机数
- 如何有效地从数组列表或字符串数组中删除所有空元素?
- 比较JUnit断言中的数组,简洁的内置方式?
- codestyle;把javadoc放在注释之前还是之后?
- 如何在Spring中定义List bean ?
- 将Set<T>转换为List<T>的最简洁的方法
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用Java重命名文件
- URL从Java中的类路径加载资源