在 Java 8 中将函数传递到 Stream 的过滤器方法
Passing a function into the Stream's filter method in Java 8
我想使用流对象上的字符串方法引用来过滤列表,为此我创建了以下比较函数:
<V, C, P> Predicate<? super P> compare(Function<P, V> valueFunction, BiPredicate<V, C> matchPredicate, C value) {
return p -> matchPredicate.test(valueFunction.apply(p), value);
}
对该方法的调用如下所示:
.filter(compare(Utilisateur::getIndividuIde, String::contains, libelleFilter.getFilterSingleValue().toUpperCase()))
这是我根据给定的过滤模式过滤列表的函数:
public List<Utilisateur> listUtilisateur(FilterDTO libelleFilter) {
List<Utilisateur> list = utilisateurDAO.listUtilisateur();
switch (libelleFilter.getOperator()) {
case TEXT_CONTAINS:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::contains, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
case TEXT_START_WITH:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::startsWith, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
case TEXT_DIFFERENT:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
case TEXT_END_WITH:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::endsWith, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
case TEXT_EQUALS:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::equals, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
default:
break;
}
return list;
}
所以我在这里面临的问题是我不想比较 Utilisateur::getIndividuIde
值,这只是我想比较的真实字符串的信息,我使用以下方法得到它:
Individu individu = individuLightSVC.donneIndividu(utilisateur.getIndividuIde(), null);
String stringToCompare = individu.getPrenom() + " " + individu.getNom()
所以在我创建的比较函数中,我需要这样的东西:
private <V, C, P> Predicate<? super P> compare(Function<P, V> valueFunction, BiPredicate<V, C> matchPredicate, C value) {
// Here I want to replace X with the string value of Utilisateur::getIndividuIde
Individu individu = individuLightSVC.donneIndividu(X, null);
String stringToCompare = individu.getPrenom() + " " + individu.getNom();
// Here I want to use stringToCompare instead of valueFunction.apply(p)
return p -> matchPredicate.test(valueFunction.apply(p), value);
}
我面临的另一个问题是如何否定方法引用谓词 String::contains
因为 String
没有 notContains
函数,你可以看到我在这一行中将其留空:
.filter(compare(Utilisateur::getIndividuIde, String::, libelleFilter.getFilterSingleValue().toUpperCase()))
你愿意帮我吗?如果有任何帮助,我将不胜感激。
第二个问题的解决方案:
感谢@Holger 的评论,String::contains
的否定可以通过否定我从 compare
函数得到的谓词来完成:
.filter(compare(Utilisateur::getIndividuIde, String::contains, libelleFilter.getFilterSingleValue().toUpperCase()).negate())
当类型应该是 String
时,您不能使用类型参数。所以只需删除 <V>
并使用 String
。然后,您写入方法的代码必须放在每次计算函数时执行的 lambda 表达式中:
private <C, P> Predicate<P> compare(
Function<P, String> valueFunction,
BiPredicate<? super String, C> matchPredicate, C value) {
return p -> {
Individu individu = individuLightSVC.donneIndividu(valueFunction.apply(p), null);
String stringToCompare = individu.getPrenom() + " " + individu.getNom();
return matchPredicate.test(stringToCompare, value);
};
}
否定可以使用,例如((BiPredicate<String,String>)String::contains).negate()
,但是只否定具有相同效果的结果谓词要简单得多,例如
.filter(compare(Utilisateur::getIndividuIde, String::contains,
libelleFilter.getFilterSingleValue().toUpperCase()).negate())
我想使用流对象上的字符串方法引用来过滤列表,为此我创建了以下比较函数:
<V, C, P> Predicate<? super P> compare(Function<P, V> valueFunction, BiPredicate<V, C> matchPredicate, C value) {
return p -> matchPredicate.test(valueFunction.apply(p), value);
}
对该方法的调用如下所示:
.filter(compare(Utilisateur::getIndividuIde, String::contains, libelleFilter.getFilterSingleValue().toUpperCase()))
这是我根据给定的过滤模式过滤列表的函数:
public List<Utilisateur> listUtilisateur(FilterDTO libelleFilter) {
List<Utilisateur> list = utilisateurDAO.listUtilisateur();
switch (libelleFilter.getOperator()) {
case TEXT_CONTAINS:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::contains, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
case TEXT_START_WITH:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::startsWith, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
case TEXT_DIFFERENT:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
case TEXT_END_WITH:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::endsWith, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
case TEXT_EQUALS:
list = list.stream()
.filter(compare(Utilisateur::getIndividuIde, String::equals, libelleFilter.getFilterSingleValue().toUpperCase()))
.collect(Collectors.toList());
break;
default:
break;
}
return list;
}
所以我在这里面临的问题是我不想比较 Utilisateur::getIndividuIde
值,这只是我想比较的真实字符串的信息,我使用以下方法得到它:
Individu individu = individuLightSVC.donneIndividu(utilisateur.getIndividuIde(), null);
String stringToCompare = individu.getPrenom() + " " + individu.getNom()
所以在我创建的比较函数中,我需要这样的东西:
private <V, C, P> Predicate<? super P> compare(Function<P, V> valueFunction, BiPredicate<V, C> matchPredicate, C value) {
// Here I want to replace X with the string value of Utilisateur::getIndividuIde
Individu individu = individuLightSVC.donneIndividu(X, null);
String stringToCompare = individu.getPrenom() + " " + individu.getNom();
// Here I want to use stringToCompare instead of valueFunction.apply(p)
return p -> matchPredicate.test(valueFunction.apply(p), value);
}
我面临的另一个问题是如何否定方法引用谓词 String::contains
因为 String
没有 notContains
函数,你可以看到我在这一行中将其留空:
.filter(compare(Utilisateur::getIndividuIde, String::, libelleFilter.getFilterSingleValue().toUpperCase()))
你愿意帮我吗?如果有任何帮助,我将不胜感激。
第二个问题的解决方案:
感谢@Holger 的评论,String::contains
的否定可以通过否定我从 compare
函数得到的谓词来完成:
.filter(compare(Utilisateur::getIndividuIde, String::contains, libelleFilter.getFilterSingleValue().toUpperCase()).negate())
当类型应该是 String
时,您不能使用类型参数。所以只需删除 <V>
并使用 String
。然后,您写入方法的代码必须放在每次计算函数时执行的 lambda 表达式中:
private <C, P> Predicate<P> compare(
Function<P, String> valueFunction,
BiPredicate<? super String, C> matchPredicate, C value) {
return p -> {
Individu individu = individuLightSVC.donneIndividu(valueFunction.apply(p), null);
String stringToCompare = individu.getPrenom() + " " + individu.getNom();
return matchPredicate.test(stringToCompare, value);
};
}
否定可以使用,例如((BiPredicate<String,String>)String::contains).negate()
,但是只否定具有相同效果的结果谓词要简单得多,例如
.filter(compare(Utilisateur::getIndividuIde, String::contains,
libelleFilter.getFilterSingleValue().toUpperCase()).negate())