处理空参数的函数式方法

Functional way to deal with null arguments

我想在工作中编写更实用的 java 代码。 但是我怎样才能重构像下面这样的东西。

该代码有效,它必须解析像 100/100 这样的字符串和 return 对整数。

private static final Pattern pattern = Pattern.compile("^(\d+)(/)(\d+)$");

public static Optional<Pair<Integer, Integer>> foo(String str) {
          var matcher = pattern.matcher(str != null ? str : "");
          return matcher.find() && matcher.groupCount() == 3 ?
            Optional.of(new Pair<Integer,Integer>(Integer.parseInt(matcher.group(1)),
              Integer.parseInt(matcher.group(3)))):
            Optional.empty();
        }
}
public static Optional<Pair<Integer, Integer>> foo(String input) {
  return Optional.ofNullable(input)
    .map(str -> pattern.matcher(str))
    .filter(matcher -> matcher.find() && matcher.groupCount() == 3)
    .map(matcher -> new Pair<Integer, Integer>(
      Integer.parseInt(matcher.group(1)),
      Integer.parseInt(matcher.group(3))
    ));
}

最好始终以 Optional 开头,这样可以避免所有空值检查。通常应该避免 Optional.of()Optional.empty() 只做最后的结果:

  • Optional.of() 没有任何进一步的操作是一种代码味道。这意味着您永远不必做任何需要空检查开始的事情。是的,有这种情况,但很少见。如果您找到这样的代码,请务必仔细查看。

    通常,代码应以 Optional.of()Optional.ofNullable() 开头,然后以 .map() 或其他方法继续。

  • Optional.empty()类似。这意味着您甚至不需要检查是否为空,只需返回一个空结果。好吧,有些情况下您可以使用此快捷方式,但通常 Optional 的要点是从 something 开始并对其进行操作。操作的结果可能会产生一个空结果。

    通常 正确 使用 Optional.empty() 是在开始时完成的——首先进行一些检查,然后生成一个空的可选项,如 an early return。小心返回 Optional.empty() last 或在您已经构建了 Optional 之后。

首先,需要固定模式以允许多个数字,并且不需要为 / 分隔符使用单独的组:

pattern = Pattern.compile("^(\d+)/(\d+)$");

接下来,输入参数可能使用Optional.ofNullableOptional::flatMap来处理解析输入字符串后返回的Optional<Pair>

public static Optional<Pair<Integer, Integer>> foo(String str) {
    return Optional.ofNullable(str)
        .flatMap(s -> pattern.matcher(s)
            .results()
            .map(mr -> new Pair<>(Integer.valueOf(mr.group(1)), Integer.valueOf(mr.group(2)))) // Stream<Pair>
            .findFirst() // Optional<Pair>
        );
}

测试:

System.out.println(foo("100/100"));
System.out.println(foo(null));
System.out.println(foo("abcd"));

输出:

Optional[100, 100]
Optional.empty
Optional.empty

更正 Java VLAZ 的 8 个友好解决方案可能如下所示:

public static Optional<Pair<Integer, Integer>> foo(String str) {
  return Optional.ofNullable(str)
    .map(pattern::matcher)
    .filter(Matcher::matches) // no need to use find() for the given pattern
    .map(matcher -> new Pair<>(
      Integer.valueOf(matcher.group(1)),
      Integer.valueOf(matcher.group(2))
    ));
}