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)