Java 流匹配尽可能多的谓词
Java stream match as many predicates as possible
希望根据定义为谓词的某些条件过滤列表(以下仅是示例):
Predicate<Person> agePredicate = p -> p.age < 30;
Predicate<Person> dobPredicate = p -> p.dateOfBirth < 1980;
Predicate<Person> namePredicate = p -> p.name.startWith("a");
List<Predicate<Person>> predicates = Arrays.asList(agePredicate, dobPredicate, namePredicate);
List<Person> shortListPersons = listPersArrays.asList(listPersons).stream().filter(p -> predicates.stream().allMatch(f -> f.test(p))).limit(10).collect(Collectors.toList());
在我找不到 anyone/enough 人的情况下,如何获得尽可能多的符合条件的人的列表 - 一种排名。
我的另一个选择是再次调用与上面相同的函数,但使用 anyMatch 代替,但它不会很准确。
有什么想法吗?谢谢!
从您的问题给出的代码开始:
List<Predicate<Person>> predicates = Arrays.asList(agePredicate, dobPredicate, namePredicate);
我们可以根据匹配的谓词数对人员列表进行排序:
List<Person> sortedListOfPeopleByPredicateMatchCOunt =
listPersArrays
.asList(listPersons)
.stream()
.sorted(
Comparator.comparingLong(p -> predicates.stream().filter(predicate -> predicate.test(p)).count()))
// Reverse because we want higher numbers to come first.
.reversed())
.collect(Collectors.toList());
只是对上述答案的扩展,如果您的目标是过滤符合尽可能多的条件的集合,您可以创建一个组合 Predicate<Person>
,然后将其用于过滤。
鉴于您的谓词列表:
List<Predicate<Person>> predicates = Arrays.asList(agePredicate, dobPredicate, namePredicate);
复合谓词可以这样创建:
Predicate<Person> compositPredicate = predicates.stream()
.reduce(predicate -> false, Predicate::or);
NOTE: As reduction operation requires an identity value and or
operation of Predicate<>
class doesn't apply any further predicates if
any one predicate turns out to be true
, I've used predicate -> false
as
an identity value.
现在,过滤集合变得更容易和更清晰:
List<Person> shortListPersons = persons.stream()
.filter(compositPredicate)
.collect(Collectors.toList());
希望根据定义为谓词的某些条件过滤列表(以下仅是示例):
Predicate<Person> agePredicate = p -> p.age < 30;
Predicate<Person> dobPredicate = p -> p.dateOfBirth < 1980;
Predicate<Person> namePredicate = p -> p.name.startWith("a");
List<Predicate<Person>> predicates = Arrays.asList(agePredicate, dobPredicate, namePredicate);
List<Person> shortListPersons = listPersArrays.asList(listPersons).stream().filter(p -> predicates.stream().allMatch(f -> f.test(p))).limit(10).collect(Collectors.toList());
在我找不到 anyone/enough 人的情况下,如何获得尽可能多的符合条件的人的列表 - 一种排名。
我的另一个选择是再次调用与上面相同的函数,但使用 anyMatch 代替,但它不会很准确。
有什么想法吗?谢谢!
从您的问题给出的代码开始:
List<Predicate<Person>> predicates = Arrays.asList(agePredicate, dobPredicate, namePredicate);
我们可以根据匹配的谓词数对人员列表进行排序:
List<Person> sortedListOfPeopleByPredicateMatchCOunt =
listPersArrays
.asList(listPersons)
.stream()
.sorted(
Comparator.comparingLong(p -> predicates.stream().filter(predicate -> predicate.test(p)).count()))
// Reverse because we want higher numbers to come first.
.reversed())
.collect(Collectors.toList());
只是对上述答案的扩展,如果您的目标是过滤符合尽可能多的条件的集合,您可以创建一个组合 Predicate<Person>
,然后将其用于过滤。
鉴于您的谓词列表:
List<Predicate<Person>> predicates = Arrays.asList(agePredicate, dobPredicate, namePredicate);
复合谓词可以这样创建:
Predicate<Person> compositPredicate = predicates.stream()
.reduce(predicate -> false, Predicate::or);
NOTE: As reduction operation requires an identity value and
or
operation ofPredicate<>
class doesn't apply any further predicates if any one predicate turns out to betrue
, I've usedpredicate -> false
as an identity value.
现在,过滤集合变得更容易和更清晰:
List<Person> shortListPersons = persons.stream()
.filter(compositPredicate)
.collect(Collectors.toList());