使用Java8流API避免长代码行的最简洁方法

时间:2015-01-19 10:16:00

标签: java lambda java-8 java-stream

我应该如何重构这样的行?

return chars.codePoints().mapToObj(cp->((!Character.UnicodeBlock.SPECIALS.equals(Character.UnicodeBlock.of(cp))) && (! Character.isISOControl(cp)))?"'"+String.valueOf(Character.toChars(cp))+"'":"0x"+Integer.toHexString(cp)).collect(Collectors.joining(","));

我应该

  • 将流重新分配给局部变量,使其更“垂直”,但将lambda保留在使用它的位置
  • 创建一个类似private String codePointToString(int cp) {...}的方法,将lambda缩短为cp->codePointToString(cp)

  • 创建一个函数常量而不是方法: private static final IntFunction<String> codePointToString = cp->{...}; 并像mapToObj(codePointToString)

  • 一样使用它

2 个答案:

答案 0 :(得分:4)

我确实会提取一个方法codePointToString(),这会使代码更容易阅读和单元测试。我每行也会有一步:

return chars.codePoints()
            .mapToObj(this::codePointToString)
            .collect(Collectors.joining(","));

为了使提取的方法的代码可读,我还会在运算符周围放置空格,并使用if而不是三元运算符

private String codePointToString(int codePoint) {
   if (!Character.UnicodeBlock.SPECIALS.equals(Character.UnicodeBlock.of(cp)) 
       && !Character.isISOControl(cp)) {
       return "'" + String.valueOf(Character.toChars(cp)) + "'";
    }
    else {
        return "0x" + Integer.toHexString(cp);
    }
}

答案 1 :(得分:3)

我要做的第一件事就是通过反转并删除过时的括号来清理条件。正如你所写的那样,我真的很难理解它,但幸运的是,我的IDE让我自动完成。所以它变成了

return chars.codePoints().mapToObj(cp->
     Character.UnicodeBlock.SPECIALS.equals(Character.UnicodeBlock.of(cp))
  || Character.isISOControl(cp)?
     "0x"+Integer.toHexString(cp):
     "'"+String.valueOf(Character.toChars(cp))+"'")
  .collect(Collectors.joining(","));

更易读。

关于其他选项,没有一般规则。您可以将条件或整个转换方法放入以其目的命名的方法中,因为这将有助于读者更多,并在表达式中引用它,例如。

mapToObj(cp->printableCodePoint(cp)?
         "0x"+Integer.toHexString(cp): "'"+String.valueOf(Character.toChars(cp))+"'")

或通过lambda表达式/方法引用,例如

mapToObj(cp->codePointToString(cp)) or mapToObj(MyClass::codePointToString)

我不建议将函数存储到第三个项目符号中的变量中。您可以通过lambda表达式从普通方法轻松创建函数,但是您无法轻松地从函数中创建普通方法。并强制代码通过codePointToStringFunction.apply(cp);调用方法而不是普通的codePointToString(cp);,其中不涉及功能操作看起来像我的编码风格。因此,在普通方法中保留可重用代码会提高其通用性。