Java 8 conditional.map()(或带有标识函数的映射)

Java 8 conditional.map()(或带有标识函数的映射),java,functional-programming,java-8,optional,Java,Functional Programming,Java 8,Optional,假设我们有布尔标志来打开/关闭流中的映射。例如修剪或不修剪 下面的例子是正确的解决方案还是有更好的方法来实现 boolean doTrim = true; optionalValue.map(doTrim ? String::trim : (x) -> x ).get()... 或: 你把事情复杂化了。如果您有一个可选可选值,您可以简单地说: if(doTrim) optionalValue=optionalValue.map(String::trim); 然后继续,例如,调用get

假设我们有布尔标志来打开/关闭流中的映射。例如修剪或不修剪

下面的例子是正确的解决方案还是有更好的方法来实现

boolean doTrim = true;
optionalValue.map(doTrim ? String::trim : (x) -> x ).get()...
或:


你把事情复杂化了。如果您有一个
可选可选值
,您可以简单地说:

if(doTrim) optionalValue=optionalValue.map(String::trim);
然后继续,例如,调用
get

但是,如果您像您的示例中那样无条件地调用
get()
,您必须确信
Optional
不是可选的,而是存在的。如果您知道存在
字符串
,则可以执行更简单的操作:

String s=optionalValue.get();
if(doTrim) s=s.trim();
如果您坚持将所有代码内联,那么您当然可以这样编写:

(doTrim? optionalValue: optionalValue.map(String::trim)).get()

但与普通的
if
语句相比,这里没有什么真正的优势。如果您有一个真正的可选值,不知道
字符串是否存在,并且不想立即调用
get
,我建议您使用我的答案的第一个版本,因为它允许以您喜欢的任何方式继续执行
可选
。在
String::trim
和标识函数之间进行选择的变体可能看起来更时髦,但与传统编程相比没有真正的优势。

两个方面:

  • 从Java语言的角度

    两者都是一样的

  • 从JVM字节码指令的角度

    他们是不同的
    (x)->x
    被转换为InvokeDynamic,而
    Function.identity()
    被转换为传统的接口方法


  • 这种方法并不真正起作用,布尔标志是一种提示问题的代码气味:而不是

    if flag then map(foo) else map(bar)
    
    您最好传递将映射到可选函数的函数,并说

    map(f)
    

    好处很明显:目前,您的代码要么修剪字符串,要么什么也不做。但下周,在某些情况下,您还需要大写、小写、修剪、反转和大写。那你怎么办?编写枚举?

    所有“内联”功能的优点是避免了可变的局部变量,这是与大块代码结合使用时难以跟踪错误的常见原因。可变的局部变量释放了在任何代码行更改它的潜力,增加了程序员的认知负荷。另一方面,不管怎样,小代码块应该是首选,在这种情况下差异会减小。@Marko Topolnik:很难说,
    doTrim
    是否是可变的,但至少它似乎起源于一个遥远的代码位置,所以可疑的设计已经存在,而在我的第二个示例中,可变局部变量的存在只是因为我不知道对
    字符串执行什么后续操作,因为问题的代码要缩小。在我的代码中,这样的操作永远不会出现,因为如果需要,源代码将能够提供
    字符串
    修剪,或者后续操作将能够在需要时为
    字符串
    处理找到正确的边界;在第二种情况下,它是
    s
    变量。OP的代码在讨论的习语中没有可变的局部变量
    doTrim
    只是一个外部参数,很可能是不可变的,可能被实际代码中的方法调用所取代。此外,我还将考虑<代码>修饰符<代码>这一问题,作为一个简单的例子来激发成语。
    if flag then map(foo) else map(bar)
    
    map(f)