Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java8中使用选项的示例正确吗?你将如何重写它?_Java_Java 8_Java Stream_Monads_Optional - Fatal编程技术网

Java8中使用选项的示例正确吗?你将如何重写它?

Java8中使用选项的示例正确吗?你将如何重写它?,java,java-8,java-stream,monads,optional,Java,Java 8,Java Stream,Monads,Optional,我已经开始使用Java的8个选项。我想和大家分享这个方法,它是一个“代码气味”的例子,我想用Java8和optionlas以及函数式(声明式)风格重写它,所以我很想看看大家对它的看法。让我们考虑这个方法: public boolean isTokenValid(String userAgent, Optional<String> apiKey) { LOGGER.info(String.format("userAgent : %s, Key ?: %s", userAge

我已经开始使用Java的8个选项。我想和大家分享这个方法,它是一个“代码气味”的例子,我想用Java8和optionlas以及函数式(声明式)风格重写它,所以我很想看看大家对它的看法。让我们考虑这个方法:

  public boolean isTokenValid(String userAgent, Optional<String> apiKey) {
    LOGGER.info(String.format("userAgent : %s, Key ?: %s", userAgent, apiKey.isPresent()));
    if ("ALFA".equalsIgnoreCase(userAgent)){
        return (apiKey != null && apiKey.isPresent()
                && ispropertyExists(ALFA_TYPE, apiKey.get()));
    }
    else {
        return (apiKey != null && apiKey.isPresent()
                && ispropertyExists(BETA_TYPE, apiKey.get()));
    }
}
public boolean isTokenValid(字符串userAgent,可选apiKey){
LOGGER.info(String.format(“userAgent:%s,Key?:%s”,userAgent,apiKey.isPresent());
if(“ALFA”。相等信号(用户代理)){
return(apiKey!=null&&apiKey.isPresent()
&&ispropertyExists(ALFA_类型,apiKey.get());
}
否则{
return(apiKey!=null&&apiKey.isPresent()
&&ispropertyExists(BETA_类型,apiKey.get());
}
}
其中,“ispropertyExists”返回布尔类型,“ALFA_类型”和“OMEGA_类型”是枚举常量。 下面是我重写这个方法的方式,目的是提高可读性和练习功能性思维方式。我添加了一些评论,来解释我的想法和我这样做的原因,如果你认为你能够改进的话,我很感激你的观点和你的方法的例子

    /**
 * We should not pass Optionals as a parameters to the methods. We
 * should use Optionals only for return value when we are not sure if value will
 * be presented at the end of the calculations or not.
 */
public boolean isTokenValid(String userAgent, String apiKey) {
    LOGGER.info(String.format("userAgent : %s, Key ?: %s", userAgent, apiKey));

    /**
     * If apiKey is null then it is incorrect. And execution will stop after
     * Optional.ofNullable(apiKey), since monad will be having null value. If apiKey
     * is not null then we still want to filter out empty strings. If after filter
     * there will be no value, then execution will stop.
     * If we have some value for apiKey then it is ok and we map the monad to the
     * userAgent value to proceed the chain of calls on monad.
     */
    Optional<String> userAgentOptional = Optional.ofNullable(apiKey).filter(StringUtils::isNotBlank)
            .map(ak -> userAgent);

    /**
     * We map "userAgent" value to boolean (if it is a alfa or not). Then
     * we map that boolean to boolean value which represents security check in db
     * itself.
     */
    Optional<Boolean> isValid = userAgentOptional.map(ua -> "ALFA".equalsIgnoreCase(ua))
            .map(isAlfa -> isAlfa ? ispropertyExists(ALFA_TYPE, apiKey)
                    : ispropertyExists(BETA_TYPE, apiKey));

    /**
     * And all in all we get value from our optional boolean. If "somehow" it is
     * ended up to be empty, then we retrun "false", if it is not empty, then the
     * value will itself be returned.
     */
    return isValid.orElse(false);
}
/**
*我们不应该将选项作为参数传递给方法。我们
*当我们不确定返回值是否正确时,应仅对返回值使用选项
*是否在计算结束时提交。
*/
公共布尔值isTokenValid(字符串userAgent,字符串apiKey){
LOGGER.info(String.format(“userAgent:%s,Key?:%s”,userAgent,apiKey));
/**
*如果apiKey为null,则它是不正确的。执行将在
*可选。ofNullable(apiKey),因为monad将具有null值。如果apiKey
*如果不为null,则我们仍希望筛选出空字符串。如果在筛选之后
*将没有值,然后执行将停止。
*如果apiKey有一些值,那么就可以了,我们将monad映射到
*userAgent值以继续monad上的调用链。
*/
可选userAgentOptional=Optional.ofNullable(apiKey).filter(StringUtils::isNotBlank)
.map(ak->userAgent);
/**
*我们将“userAgent”值映射为布尔值(如果它是alfa或不是)
*我们将该布尔值映射为表示db中的安全检查的布尔值
*本身。
*/
可选isValid=userAgentOptional.map(ua->“ALFA.equalsIgnoreCase(ua))
.map(isAlfa->isAlfa?ispropertyExists(阿尔法类型,apiKey)
:ispropertyExists(BETA_类型,apiKey));
/**
*总之,我们从可选的布尔值中得到值。如果“不知何故”它是
*结果是空的,那么我们重新运行“false”,如果它不是空的,那么
*值本身将被返回。
*/
返回有效。或返回(假);
}

谢谢。

如果你喜欢函数式风格,首先不要使用
null
,或者至少不要到处传递
null

但如果您必须使用
null
,以下是我的代码:

public boolean isTokenValid(String userAgent, String apiKey) {
    final Enum type = "ALFA".equalsIgnoreCase(userAgent) ? ALFA_TYPE : BETA_TYPE;
    return
        Optional.ofNullable(apiKey)
        .filter(ak -> ispropertyExists(type, ak))
        .isPresent();
}

注:功能性风格并不意味着试图把所有东西都链接起来,避免临时值。相反,它是关于使用纯函数不可变数据。不管风格如何,我们的目标是编写可读且合理的代码。纯粹的函数和不变的数据非常适合实现这一目标。

我觉得你做得太多太复杂了。我同意,一般来说,我们不应该将
可选的
作为参数传递给方法。如果您不能要求传递的
apiKey
为非空,我的建议是:

public boolean isTokenValid(String userAgent, String apiKey) {
    LOGGER.info(String.format("userAgent : %s, Key : %s", userAgent, apiKey));
    if (apiKey == null || apiKey.isEmpty()) {
        return false;
    }
    return ispropertyExists(
            userAgent.equalsIgnoreCase("ALFA") ? ALFA_TYPE : BETA_TYPE, apiKey);
}

我会发现这非常简单。对于您的案例,不需要使用
可选的

我会将所有操作组合在一个链式语句中,并返回结果,避免不必要的
可选的
变量

 return Optional.ofNullable(apiKey)
                .filter(StringUtils::isNotBlank)
                .map(ak -> userAgent)
                .map("ALFA"::equalsIgnoreCase)
                .map(isAlfa -> isAlfa ? ALFA_TYPE : BETA_TYPE)
                .map(type -> ispropertyExists(type, apiKey))
                .orElse(false);

难道你不能把那些
map
s链合并成一个,然后继续工作…除了可选之外,作为一个参数本身是一种不好的做法。好吧,那么你的观点是-一切都好,但只需将它收缩为:“可选的。不可用的(apiKey)。过滤器(…).map(…).map(…).map(…).map(…).orElse(false);“我的理解正确吗?谢谢你的意见,我同意去掉传递到方法中的可选参数是一个好主意,我在我的示例中这样做了。我同意我们不应该将空值传递到方法中,但对于目前阳光灿烂的印度的离岸团队来说,这是不可能的,除非我们重写整个代码库并重新雇用离岸团队,所以我很好奇您在这种情况下的意见。你考虑过我提供的第二个例子吗?谢谢你的意见。因此,在您的示例中,您已经更改了“ispropertyExists”函数的类型参数,现在在您的示例中,它采用“boolean”而不是“ENUM”。如果没有更改“ispropertyExists”签名,您将如何重写它?不,我没有更改。“类型”“变量仍然是一个枚举。你能再检查一遍吗?是的,你是对的,我很抱歉。谢谢你的意见。我完全同意,对于那些习惯命令式写作的人来说,它更简单。:)我同意,对于习惯命令式写作的人来说,我过于复杂了。我也喜欢你的例子。:)谢谢你的意见!还有。”您将如何使用monads重写?:)非常感谢您的意见,您以函数式风格编写有多久了?除了java8之外,您还使用其他语言吗?(可能是haskell)