我喜欢Java中的可选
。在一个简单的类中,它允许我清楚地识别返回类型和参数,这些类型和参数可能可用,也可能不可用。
我要解决的一件事是,必须将其分配给一个短期变量,然后将其继承到后续的每个范围中。
当使用这样的选项时,我喜欢使用简单的变量名称opts
:
Optional<ThingA> opt = maybeGetThing();
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
...
但当我需要在这个范围内使用变量名时。。。
void method() {
Optional<ThingA> opt = maybeGetThing();
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// Duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
}
}
我可以使用诸如optA
和optB
之类的东西。但是我想知道是否有另一种方法可以编写这段代码,而不必枚举我的临时变量。这有点像懒惰的变量名,比如a
aaaa
aaaaabbb
或其他东西。
我不想像这样明确地命名我所有的选项:
Optional<ThingA> optUsefulVariableName = maybeGetThing();
if (optUsefulVariableName.isPresent()) {
ThingA usefulVariableName = optUsefulVariableName.get();
...
虽然准确,但却极其冗长。我还尝试使用像opt
和I
这样的一次性名称,以表明这些名称实际上只是暂时的,不应超出其直接范围(即使它们将被继承)。
更新:
我已经看到了使用ifPresent()
的建议,但我不知道如何在可选项为空时也需要执行操作的情况下使用它:
void method() {
Optional<ThingA> opt = maybeGetThing();
if (!opt.isPresent()) {
doSomethingOnlyHere();
return;
}
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// Duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
}
}
当我尝试使用ifPresent()
进行重构时:
void method() {
// Doesn't handle instance where I need side effects on an empty optional
maybeGetThing().ifPresent(usefulVariableName -> {
...
}
}
从Java9开始
void method() {
maybeGetThing().ifPresentOrElse(
usefulVariableName -> {
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// No duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
},
this::doSomethingOnlyHere
);
}
我的经验是,你很少需要或想要使用isPresent
和/或get
,它们是低级的。对于基本的东西,ifPresent
(带f
)和ifPresetnOrElse
都可以。其他人则认为map
和flatMap
也非常有用。
消除变量和调用Optional#get
的最基本方法是使用Optional。ifPresent
,如果可选项有值,则调用函数。
maybeGetThing().ifPresent(val -> {
// do stuff with side effects here
});
使用Optional仍然是一种非常有限的方式,因为Optional的主要目的之一是促进函数式编程。如果你是个初学者,这可能会让你有点不知所措,但我们的想法是让函数返回一些东西,而不是依赖于副作用的函数。依赖于副作用的功能无法链接在一起,通常更难推理。
从技术上讲,Optional
是一种叫做函子的东西(来自范畴论)。它是一个围绕一个值(无论T
是什么)的包装器,它允许通过一系列操作传递该值,对其进行操作,并将其传递给下一个操作,直到我们得到我们想要的,然后操作链以一个终端(即最终)操作结束。如果存在,终端操作可能会返回未包装的值;如果不存在,终端操作可能会抛出或返回一些默认值。
对于可选,如果值不存在,它将跳过任何后续操作。
有一些常见的操作,比如map、filter、flatMap(好的,这是一个Monad操作)和其他更具体的java操作,比如Optional#orElse
和Optional#orelsetrow
。
要重构示例代码,可以这样做。
void method() {
return maybeGetThing().flatMap(val -> {
// eek side effects
val.doA();
val.doB();
val.doC();
return val.maybeAnotherThing();
});
}
flatMap
是一种将一种可选类型转换为另一种可选类型的方法。如果返回值不是可选的,则使用map。
您可以看到,我们已经不再需要返回值的名称,而是支持命名lambda函数的参数。lambda函数具有作用域,因此如果需要的话,可以重用这些名称。
我通常喜欢提供可运行的代码,所以这里有一个我所说的可运行的人为例子。
import java.util.Optional;
class DummyClass {
private int val = 0;
public void doA(){ val += 1; }
public void doB(){ val += 2; }
public void doC(){ val += 3; }
public Optional<String> maybeAnotherThing(){
return Optional.of(Integer.toString(val));
}
}
public class UseOptional5 {
Optional<DummyClass> maybeGetThing(){
return Optional.of(new DummyClass());
}
String method() {
return maybeGetThing()
// you can put other operations here
.flatMap(val -> {
// eek side effects
val.doA();
val.doB();
val.doC();
return val.maybeAnotherThing();
})
// you can put other operations here too
.orElseThrow(() -> new IllegalArgumentException("fail!!"));
}
public static void main(String args[]) {
UseOptional5 x = new UseOptional5();
System.out.println(x.method());
}
}
问题内容: 有没有很好的方法来获取下一个星期三的日期?也就是说,如果今天是星期二,我想获取本周星期三的日期;如果今天是星期三,我想知道下星期三的日期;如果今天是星期四,我想获取下周的星期三日期。 谢谢。 问题答案: 基本算法如下: 获取当前日期 取得星期几 与周三找到不同 如果差异不是正数,则加7(即坚持下一个到来/将来的日期) 增加差异 这是一个片段,展示了如何使用: 相对于我现在的位置,上述代
我的问题是如何从多个(或分片)TFR记录中获取批输入。我读过这个例子https://github.com/tensorflow/models/blob/master/inception/inception/image_processing.py#L410.以培训集为例,基本管道是:(1)首先生成一系列TF记录(例如,,,…),(2) 从这些文件名生成一个列表,并将它们输入到获取队列,(3)同时生成
除了把它们全部输入外,还有没有更好的方法在字符串中列出它们?
我想使用以下循环创建一个新列。表中只有“open”和“start”列。我想创建一个新列“startopen”,如果“start”等于1,那么“startopen”等于“open”。否则,“startopen”等于此新创建列上方行中的任何“startopen”。目前,我能够通过以下方式实现这一点: 这有效,但对于大型数据集来说非常慢。是否有任何内置函数可以更快地完成此操作?
我在github的sping-hateoas存储库中也看到了一个类似的问题,但答案是在stackoverflow中提问。 我在项目中使用spring hateoas PagedResources来返回APIendpoint的响应。我现在有了一个APIendpoint,其中的计数信息将不可用,因此我使用的是一个切片,而不是一个页面。但是,在构建响应时,我没有找到SlicedResources,只有P
我正试图将一个阻塞消费者集成为Reactor铝-SR1中的助焊剂订户。我想使用一个并行调度器,并发地执行阻塞操作。 我实现了一个主类来描述我意图: