我想根据谓词筛选java.util.Collection。
当前回答
从java 9开始收集。启用过滤:
public static <T, A, R>
Collector<T, ?, R> filtering(Predicate<? super T> predicate,
Collector<? super T, A, R> downstream)
因此过滤应该是:
collection.stream().collect(Collectors.filtering(predicate, collector))
例子:
List<Integer> oddNumbers = List.of(1, 19, 15, 10, -10).stream()
.collect(Collectors.filtering(i -> i % 2 == 1, Collectors.toList()));
其他回答
假设您使用的是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流如何工作的更多示例,请参见这里。
您可以使用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
https://code.google.com/p/joquery/
支持不同的可能性,
给定的集合,
Collection<Dto> testList = new ArrayList<>();
的类型,
class Dto
{
private int id;
private String text;
public int getId()
{
return id;
}
public int getText()
{
return text;
}
}
过滤器
Java 7
Filter<Dto> query = CQ.<Dto>filter(testList)
.where()
.property("id").eq().value(1);
Collection<Dto> filtered = query.list();
Java 8
Filter<Dto> query = CQ.<Dto>filter(testList)
.where()
.property(Dto::getId)
.eq().value(1);
Collection<Dto> filtered = query.list();
同时,
Filter<Dto> query = CQ.<Dto>filter()
.from(testList)
.where()
.property(Dto::getId).between().value(1).value(2)
.and()
.property(Dto::grtText).in().value(new string[]{"a","b"});
排序(也可用于Java 7)
Filter<Dto> query = CQ.<Dto>filter(testList)
.orderBy()
.property(Dto::getId)
.property(Dto::getName)
Collection<Dto> sorted = query.list();
分组(也可用于Java 7)
GroupQuery<Integer,Dto> query = CQ.<Dto,Dto>query(testList)
.group()
.groupBy(Dto::getId)
Collection<Grouping<Integer,Dto>> grouped = query.list();
连接(也可用于Java 7)
考虑到,
class LeftDto
{
private int id;
private String text;
public int getId()
{
return id;
}
public int getText()
{
return text;
}
}
class RightDto
{
private int id;
private int leftId;
private String text;
public int getId()
{
return id;
}
public int getLeftId()
{
return leftId;
}
public int getText()
{
return text;
}
}
class JoinedDto
{
private int leftId;
private int rightId;
private String text;
public JoinedDto(int leftId,int rightId,String text)
{
this.leftId = leftId;
this.rightId = rightId;
this.text = text;
}
public int getLeftId()
{
return leftId;
}
public int getRightId()
{
return rightId;
}
public int getText()
{
return text;
}
}
Collection<LeftDto> leftList = new ArrayList<>();
Collection<RightDto> rightList = new ArrayList<>();
可以像这样连接,
Collection<JoinedDto> results = CQ.<LeftDto, LeftDto>query().from(leftList)
.<RightDto, JoinedDto>innerJoin(CQ.<RightDto, RightDto>query().from(rightList))
.on(LeftFyo::getId, RightDto::getLeftId)
.transformDirect(selection -> new JoinedDto(selection.getLeft().getText()
, selection.getLeft().getId()
, selection.getRight().getId())
)
.list();
表达式
Filter<Dto> query = CQ.<Dto>filter()
.from(testList)
.where()
.exec(s -> s.getId() + 1).eq().value(2);
这一点,再加上缺少真正的闭包,是我对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,特别是lambda表达式,你可以像下面的例子那样简单:
myProducts.stream().filter(prod -> prod.price>10).collect(Collectors.toList())
其中,对于myProducts集合中的每个产品,如果prodc .price>10,则将该产品添加到新的过滤列表中。
推荐文章
- 使用Jackson将JSON字符串转换为漂亮的打印JSON输出
- Android - SPAN_EXCLUSIVE_EXCLUSIVE跨度不能为零长度
- Javadoc @see或{@link}?
- 在准备语句中使用“like”通配符
- Android Eclipse -无法找到*.apk
- javac和Eclipse编译器之间的区别是什么?
- 工厂模式和策略模式之间的区别是什么?
- 在Java中使用正则表达式提取值
- 如何允许所有网络连接类型HTTP和HTTPS在Android(9)馅饼?
- Intellij IDEA Java类在保存时不能自动编译
- 何时使用Mockito.verify()?
- 在maven中安装mvn到底做什么
- 不可变与不可修改的集合
- 如何在JSON中使用杰克逊更改字段名
- GSON -日期格式