使用Java8流api避免长代码行的最干净方法

使用Java8流api避免长代码行的最干净方法,java,lambda,java-8,java-stream,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)).col

我应该如何像这样重构行

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保留在使用它的地方
  • 创建一个类似于
    私有字符串codepointostring(int cp){…}
    的方法,将lambda缩短为
    cp->codepointostring(cp)

  • 创建函数常量而不是方法:
    private static final IntFunction codepointostring=cp->{…}
    并像
    mapToObj(codepointostring)


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

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

我要做的第一件事是通过反转条件并删除过时的括号来清理条件。正如您所写的,我真的很难理解它,但谢天谢地,我的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表达式轻松地从普通方法创建函数,但无法轻松地从函数中创建普通方法。以及通过
codepointostringfunction.apply(cp)强制代码调用方法而不是普通的
codepointostring(cp)在不涉及任何功能操作的情况下,我觉得编码风格很糟糕。因此,在普通方法中保留可重用代码提高了它的通用性。

虽然这两个答案或多或少都是相同的,但我遵循@Holger关于函数常数的论点。