Java 仅筛选请求中存在的参数

Java 仅筛选请求中存在的参数,java,java-8,java-stream,Java,Java 8,Java Stream,有很多关于Java8Lambda操作的文章,但是我直到现在才找到我需要的。我试图让他们接受我的方法,但不幸的是,我没有成功 假设您有POJO中的请求,例如 public class DummyRequest { private String name; private String surname; private String country; public String getName() { return name; }

有很多关于Java8Lambda操作的文章,但是我直到现在才找到我需要的。我试图让他们接受我的方法,但不幸的是,我没有成功

假设您有POJO中的请求,例如

public class DummyRequest {

    private String name;
    private String surname;
    private String country;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country= country;
    }

}
在REST/SOAP请求期间,姓氏变量将被分配为null

List<Person> persons = Arrays.asList(
                new Person("maria", "gambert", "italy"),
                new Person("jack", "johson", "usa"),
                new Person("johnson", "jack", "usa"),
                new Person("kate", "julia", "spain"),
                new Person("jack","bob","uk");

DummyRequest dr = new DummyRequest();
dr.setName("jack");
dr.setCountry("usa");

但是,我不知道哪些字段将
null
,哪些不会。如何仅根据非空请求参数筛选数据?

如果只想通过
dummyRequest
的非空属性进行筛选,只需向每个
谓词添加空检查即可:

List<Person> result4 =
    persons.stream()
           .filter(x -> dummyRequest.getSurname() == null || dummyRequest.getSurname().equals(x.getSurname()))
           .filter(x -> dummyRequest.getName() == null || dummyRequest.getName().equals(x.getName()))
           .filter(x -> dummyRequest.getCountry() == null || dummyRequest.getCountry().equals(x.getCountry()))
           .collect(Collectors.toList());
列表结果4=
人流()
.filter(x->dummyRequest.getNames()==null | | dummyRequest.getNames().equals(x.getNames())
.filter(x->dummyRequest.getName()==null | | dummyRequest.getName().equals(x.getName())
.filter(x->dummyRequest.getCountry()==null | | dummyRequest.getCountry().equals(x.getCountry())
.collect(Collectors.toList());

我将为此定义一个静态方法,因为您要重复代码很多次:

private static boolean nullableOrEqual(String left, String right) {
    return left == null || left.equals(right);
}
然后用法是:

List<Person> result = persons.stream()
            .filter(x -> nullableOrEqual(dr.getSurname(), x.getSurname()))
            .filter(x -> nullableOrEqual(dr.getCountry(), x.getCountry()))
            .filter(x -> nullableOrEqual(dr.getName(), x.getName()))
            .collect(Collectors.toList());
列表结果=persons.stream()
.filter(x->nullableOrEqual(dr.GetLastname(),x.GetLastname())
.filter(x->nullableOrEqual(dr.getCountry(),x.getCountry())
.filter(x->nullableOrEqual(dr.getName(),x.getName()))
.collect(Collectors.toList());

如果只想应用
dummyRequest
包含非空值的筛选器,则必须动态构建流以获得最有效的解决方案

这可以通过实现一个有条件地应用过滤器的助手方法轻松实现:

public static <T, V> Stream<T> filterIfNotNull(Stream<T> stream, V filterValue, Function<T, V> property) {
    if (filterValue == null) {
        return stream;
    }

    return stream.filter(t -> filterValue.equals(property.apply(t)));
}

此技术保证对请求属性的null检查只应用一次。

您可以创建一个
checkNonNullProperties
helper方法,该方法返回一个
谓词
,该谓词只检查
DummyRequest
实例的非null属性是否相等。您可以按如下方式使用它:

Predicate<Person> condition = checkNonNullProperties(
    Arrays.asList(
        dr.getCountry(),
        dr.getName(),
        dr.getSurname()),
    Arrays.asList(
        Person::getCountry,
        Person::getName,
        Person::getSurname));

List<Person> result = people.stream()
    .filter(condition)
    .collect(Collectors.toList());
谓词条件=检查非空属性(
Arrays.asList(
getCountry()博士,
getName()博士,
GetLastname()博士,
Arrays.asList(
人物:getCountry,
Person::getName,
人名:(姓),;
列表结果=people.stream()
.过滤器(条件)
.collect(Collectors.toList());
助手方法:

private static <T> Predicate<T> checkNonNullProperties(
        List<?> values,
        List<Function<T, ?>> extractors) {
    return IntStream.range(0, values.size()).mapToObj(i ->
            (Predicate<T>) t -> {
                Object value = values.get(i);
                Object property = extractors.get(i).apply(t);
                return value == null || value.equals(property);
            })
            .reduce(t -> true, Predicate::and);
}
私有静态谓词checkNonNullProperties(
列出值,
列表提取器){
返回IntStream.range(0,values.size()).mapToObj(i->
(谓语)t->{
对象值=值。获取(i);
对象属性=提取器.get(i).apply(t);
返回值==null | | value.equals(属性);
})
.reduce(t->true,谓词::and);
}
checkNonNullProperties
方法接收要检查相等性的值列表和将从返回谓词的参数中提取属性的函数列表。仅针对非空的值,将检查提取的属性是否与其对应的值相等

我使用
IntStream
在两个列表上驱动迭代。在
mapToObj
方法中,我将流的
int
值映射到一个谓词,当提供的值为
null
或等于提取的属性时,该谓词返回
true


最后,通过
predicate::and
操作符将这些谓词简化为最终谓词。在
reduce
调用中,我为
操作符提供了标识谓词,它是
t->true
(总是返回true)。

不必要的装箱
布尔值的存在。true
表明在编写
left==null时,您可能会有更复杂的想法?Boolean.TRUE:left.equals(right)
,然而,结果是一个表达式,可以简化为
left==null | | | left.equals(right)
@Holger,所以你现在开始读心术:)我确实想写一些最后对我来说不起作用的东西,你说得对
Predicate<Person> condition = checkNonNullProperties(
    Arrays.asList(
        dr.getCountry(),
        dr.getName(),
        dr.getSurname()),
    Arrays.asList(
        Person::getCountry,
        Person::getName,
        Person::getSurname));

List<Person> result = people.stream()
    .filter(condition)
    .collect(Collectors.toList());
private static <T> Predicate<T> checkNonNullProperties(
        List<?> values,
        List<Function<T, ?>> extractors) {
    return IntStream.range(0, values.size()).mapToObj(i ->
            (Predicate<T>) t -> {
                Object value = values.get(i);
                Object property = extractors.get(i).apply(t);
                return value == null || value.equals(property);
            })
            .reduce(t -> true, Predicate::and);
}