Java 滥用可选的#map考虑到缺少可选的#peek方法

Java 滥用可选的#map考虑到缺少可选的#peek方法,java,java-8,Java,Java 8,考虑以下类别: ClassA { } ClassB { private ClassA classA; // getters and setters } 由于Optional上没有可用的peek方法,这是否被视为滥用Optional#map方法: return myService.findA() .flatMap(a -> myService.findB(a) // also returns optional .m

考虑以下类别:

ClassA {
}

ClassB {
    private ClassA classA;

    // getters and setters
}
由于
Optional
上没有可用的
peek
方法,这是否被视为滥用
Optional#map
方法:

return myService.findA()
        .flatMap(a -> myService.findB(a) // also returns optional
                    .map(b -> {
                            b.setClassA(a);
                            return b;
                        }))
        .map(d -> MyType.of(d)) // MyType being other class
        .orElse(MyType.empty());
也可以这样写:

Optional<ClassA> optionalA = myService.findA();

if (optionalA.isPresent()) {
    Optional<ClassB> optionalB = myService.findB(optionalA.get());

    if (optionalB.isPresent()) {
        ClassB classB = optionalB.get();
        classB.setClassA(optionalA.get());
        return MyType.of(classB);
}
return MyType.empty();
可选选项a=myService.findA();
如果(可选a.isPresent()){
可选optionalB=myService.findB(optionalA.get());
如果(可选B.isPresent()){
ClassB ClassB=optionalB.get();
setClassA(optionalA.get());
返回MyType.of(类别B);
}
返回MyType.empty();

两个实现执行相同的逻辑,是否一个比另一个更好?

我可能更喜欢第一个实现,因为可选功能在转换中提供了主要功能,我认为最好将其充分利用。

我可能更喜欢自主要功能以来的第一个实现在转换中可选提供的功能,我认为最好将其充分利用。

对我来说,
myService.findB(a)
并不意味着
b.setClassA(a)
,因为它在范围内都有,但无论如何,这里没有必要滥用
map

return myService.findA()
    .flatMap(a -> {
        Optional<B> oB = myService.findB(a);
        oB.ifPresent(b -> b.setClassA(a));
        return oB;
    })
    .map(MyType::of).orElse(MyType.empty());
返回myService.findA()
.flatMap(a->{
可选oB=myService.findB(a);
oB.ifPresent(b->b.setClassA(a));
返回oB;
})
.map(MyType::of).orElse(MyType.empty());

对我来说,
myService.findB(a)
并不意味着
b.setClassA(a)
,这看起来很奇怪,因为它在作用域中同时存在这两个属性,但无论如何,这里没有必要滥用
map

return myService.findA()
    .flatMap(a -> {
        Optional<B> oB = myService.findB(a);
        oB.ifPresent(b -> b.setClassA(a));
        return oB;
    })
    .map(MyType::of).orElse(MyType.empty());
返回myService.findA()
.flatMap(a->{
可选oB=myService.findB(a);
oB.ifPresent(b->b.setClassA(a));
返回oB;
})
.map(MyType::of).orElse(MyType.empty());

因此,当您应用功能设计原则时,您永远不会在适当的位置更新状态。这意味着没有任何数据结构允许这样做(就像您的
ClassB
与该setter一起使用的情况一样)。您宁愿使用更新的值返回该类的新实例。如果您这样做,则无需“滥用”可以是
map
flatMap
,但您可以使用闭包:

return myService.findA()
    .flatMap(a -> myService.findB(a).map(b -> b.copyWith(a)))
    .map(MyType::of)
    .orElse(MyType.empty());

因此,当您应用功能设计原则时,您永远不会在适当的位置更新状态。这意味着没有任何数据结构允许这样做(就像您的
ClassB
与该setter一起使用的情况一样)。您宁愿使用更新的值返回该类的新实例。如果这样做,就没有必要“滥用”“无论是
map
还是
flatMap
,您都可以使用闭包:

return myService.findA()
    .flatMap(a -> myService.findB(a).map(b -> b.copyWith(a)))
    .map(MyType::of)
    .orElse(MyType.empty());

(a)是的,这是滥用,因为
map
可能不会有任何副作用,以及(b)“旧式”代码可能是一个更详细的机器人,但它非常、更清晰、更容易理解。同时,java doc for peek表示:这种方法的存在主要是为了支持调试。因此,对于状态突变
peek
map
,使用什么是一个开放的问题。请查看和@AntonBalaniuc。已经有了
ifPresent
在类
Optional
中,该类显式地用于执行操作。@tobias_k不是“可能”而是“绝对”。传递给map的方法应该是函数,根据定义是纯粹的。IMHO,(a)是的,这是滥用,因为
map
可能没有任何副作用,(b)旧样式代码可能是一个更详细的机器人,但它非常、更清晰、更容易理解。同时,java doc for peek表示:这种方法的存在主要是为了支持调试。因此,对于状态突变
peek
map
,使用什么是一个开放的问题。请查看和@AntonBalaniuc。已经有了
ifPresent
在类
Optional
中,该类明确用于执行操作。@tobias_k不是“可能”而是“绝对”。传递给map的方法应该是函数,这些函数根据定义是纯函数。
Optional
的主要功能是提供一种方法,以声明性和方便的方式处理缺席的影响(eventhough
java.util.Optional
被破坏)
Optional
的主要功能是提供一种以声明和方便的方式处理缺勤影响的方法(eventhough
java.util.Optional
被破坏),这比OP的版本(两者都是IMHO)清晰得多,但这是否仍然是对
flatMap
的滥用,就像它对
map
的滥用一样?@tobias_k原始版本中
map
的问题是,它仅仅是为了执行一个有副作用的动作而添加的;它并没有真正将值映射到其他东西上。我答案中的
flatMap
仍然在int中使用结束方式,执行一个计算结果为另一个
可选
的操作。如果您仍然不确信,可以封装
myService.findB(a);
oB.ifPresent(b->b.setClassA(a))
自己创建一个新方法,并在
flatMap
中调用此方法;如前所述,我希望
findB
在语义上作为操作的一部分时首先这样做。这比OP的版本(两者都是IMHO)清楚得多,但这是否仍然是对
flatMap
的滥用,就像它对
map
的滥用一样?@tobias_k原始版本中
map
的问题是,它仅仅是为了执行一个有副作用的动作而添加的;它并没有真正将值映射到其他东西上。我答案中的
flatMap
仍然在int中使用结束方式,执行一个计算结果为另一个
可选
的操作。如果您仍然不确信,您可以将
myService.findB(a);
oB.ifPresent(b->b.setClassA(a));
单独封装到一个新方法中,并在
flatM中调用此方法