以简洁的方式在java8谓词中记录条件结果

时间:2018-06-20 17:24:49

标签: logging java-8 predicate

我有这样的代码:

Predicate<String> notNull = input -> (input != null);
Predicate<String> notEmpty = input -> (input.trim().length() > 0);

我的验证器方法正在使用它,如下所示:

public boolean isInputValid(String input){
    return (notNull.and(notEmpty)).test(input);
}

每当我调用isInputValid(<myInputString>)方法时,它将返回true或false,但是,如果我想记录哪个条件恰好失败,我该如何在Java8中做到这一点而又不将谓词notNull和notEmpty转换为方法。

下面的示例将Predicate notNull转换为方法将实现我记录输入问题的目标,但它太冗长了。有没有更好/更简洁的方法?

private Predicate<String> notNull(){
    return input -> {
        if(input == null){
            log.warn("NULL input");
            return false;
        }
        return true;
    };
}

2 个答案:

答案 0 :(得分:6)

一种方法是创建一个高阶函数,该函数将一些记录代码包装在现有谓词周围,并返回可以代替原始谓词使用的谓词。这是此类功能的示例:

static <T> Predicate<T> loggingPredicate(String label, Predicate<? super T> pred) {
    return t -> {
        boolean r = pred.test(t);
        System.out.printf("%s: %s => %s%n", label, t, r);
        return r;
    };
}

这将打印出每个呼叫的输入和结果。它还带有一个标签,以便您可以从日志中得知正在评估哪个谓词。您可以调整它,使其仅在谓词返回false或类似的内容时才输出日志消息。当然,您可以调整它以使用所需的任何日志记录框架,而不是打印到stdout。

然后,您可以使用现有谓词并将其包装在对此函数的调用中:

Predicate<String> notNull = loggingPredicate("notNull", input -> (input != null));
Predicate<String> notEmpty = loggingPredicate("notEmpty", input -> (input.trim().length() > 0));

然后像以前一样使用notNullnotEmpty。每次对其中之一进行评估时,您都会收到一条日志消息。

答案 1 :(得分:4)

对此没有内置的解决方案,但是您可以创建自定义可记录谓词来完成这项工作。

@FunctionalInterface
interface LPredicate<T> extends Predicate<T>{
    default boolean testAndLog(T t, String prefix){
        boolean result = this.test(t);
        if(!result){
            log.warn(prefix + " " + t);
        }
        return result;
    }
}

完整的测试码

import java.util.function.Predicate;

public class FunctionLog {
    static MLog log = new MLog();

    @FunctionalInterface
    interface LPredicate<T> extends Predicate<T>{
        default boolean testAndLog(T t, String prefix){
            boolean result = this.test(t);
            if(!result){
                log.warn(prefix + " " + t);
            }
            return result;
        }
    }

    static LPredicate<String> notNull = input -> (input != null);
    static LPredicate<String> notEmpty = input -> (input.trim().length() > 0);  

    public static void main(String[] args) {        
        System.out.println("Case1: " + isInputValid(""));
        System.out.println("Case2: " + isInputValid(null));
        System.out.println("Case3: " + isInputValid("hello"));
    }

    public static boolean isInputValid(String input){       
        return notNull.testAndLog(input, "NULL Check Failed") && notEmpty.testAndLog(input, "EMPTY Check Failed");
    }
}

/**
 * Just a mock log class
 *
 */
class MLog {
    void warn(String str) {
        System.out.println(str);
    }
}