【问题标题】:Functional way to deal with null arguments处理空参数的函数式方法
【发布时间】:2021-12-22 09:53:26
【问题描述】:

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

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

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();
        }
}

【问题讨论】:

  • 您的代码有几个拼写错误,所以它不能像发布的那样工作。下次我建议你直接剪切和粘贴。

标签: java functional-programming refactoring


【解决方案1】:
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 之后。

【讨论】:

  • 这是最好的解决方案
【解决方案2】:

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

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

接下来,输入参数最好使用Optional.ofNullableOptional::flatMap处理解析输入字符串后返回的Optional&lt;Pair&gt;

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

由 VLAZ 更正的 Java 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))
    ));
}

【讨论】:

  • 1.如果可选项为空,则不需要.orElse(Optional.empty());,这已经是您所得到的了。 2、Optional上的.map()不应该是flatMap()吗?看来这应该产生Optional&lt;Optional&lt;Pair&gt;&gt;
  • 是的,不错的收获!我提供了orElse 以使其与Optional.map 一起使用:)
  • java 9 已弃用新整数
  • 好的,这是专门在 Java 8 上编译的;改为Integer.valueOf以避免不必要的拳击
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-20
  • 2019-03-25
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 2016-02-28
  • 1970-01-01
相关资源
最近更新 更多