对Java 8可选*值的操作。

对Java 8可选*值的操作。,java,java-8,Java,Java 8,Java8有许多可选类,如OptionalDouble,optionalnt,OptionalLong 是否有一种很好的方法可以使用相同类型的可选值进行操作?也就是说,我希望能够做到: OptionalDouble d1 = OptionalDouble.of(1.); OptionalDouble d2 = OptionalDouble.of(2.); OptionalDouble d3 = OptionalDouble.of(3.); OptionalDouble result = d1.

Java8有许多可选类,如
OptionalDouble
optionalnt
OptionalLong

是否有一种很好的方法可以使用相同类型的可选值进行操作?也就是说,我希望能够做到:

OptionalDouble d1 = OptionalDouble.of(1.);
OptionalDouble d2 = OptionalDouble.of(2.);
OptionalDouble d3 = OptionalDouble.of(3.);

OptionalDouble result = d1.add(d2).multiply(d3);
当然,如果其中任何一个是“空的”,那么结果应该是空的。在谷歌搜索了一下之后,我发现了一些代码示例,其中人们正在使用这些函数(例如,
add
),但它不再是API的一部分(现在?)。

奇怪。引用有一个方法,您可以使用它来做类似于您想要做的事情,但它似乎不在基本选项中。我相信您目前唯一的办法是使用
optionaldough::isPresent
optionaldough::ifPresent


或者,您可以定义自己的helper
add
方法,或者定义自己的
OptionalDouble
类来包含这些方法。

您可以创建自己的实现来封装
OptionalDouble
,这里要考虑的一个非常重要的问题是,您的封装类应该是不可变的,以防止混淆:<代码> OptionalDouble <代码>本身是不可变的。< /P> 为了可读性,与静态方法相比,最好使用自己的实现

我用最基本的行为创造了自己的行为:

public class OptionalDoubleImproved {
    private static final OptionalDoubleImproved EMPTY = OptionalDoubleImproved.of(OptionalDouble.empty());

    private final OptionalDouble optionalDouble;

    private OptionalDoubleImproved(final OptionalDouble optionalDouble) {
        this.optionalDouble = Objects.requireNonNull(optionalDouble);
    }

    public static OptionalDoubleImproved of(final OptionalDouble optionalDouble) {
        return new OptionalDoubleImproved(optionalDouble);
    }

    public OptionalDoubleImproved applyFunction(final DoubleBinaryOperator operator, final OptionalDouble operand) {
        Objects.requireNonNull(operator);
        Objects.requireNonNull(operand);
        if (!optionalDouble.isPresent() || !operand.isPresent()) {
            return EMPTY;
        }
        return OptionalDoubleImproved.of(OptionalDouble.of(operator.applyAsDouble(optionalDouble.getAsDouble(), operand.getAsDouble())));
    }

    public OptionalDouble get() {
        return optionalDouble;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 53 * hash + Objects.hashCode(this.optionalDouble);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final OptionalDoubleImproved other = (OptionalDoubleImproved) obj;
        if (!Objects.equals(this.optionalDouble, other.optionalDouble)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "OptionalDoubleImproved[" + optionalDouble + "]";
    }
}
然后可以用作:

OptionalDouble d1 = OptionalDouble.of(1.);
OptionalDouble d2 = OptionalDouble.of(2.);
OptionalDouble d3 = OptionalDouble.of(3.);

OptionalDouble result = OptionalDoubleImproved.of(d1)
        .applyFunction((a, b) -> a + b, d2)
        .applyFunction((a, b) -> a * b, d3)
        .get();

我会使用普通的
double

double d1 = 1, d2 = 2, d3 = 3;
if (condition)
    d1 = Double.NaN;
double result = (d1 + d2) * d3; // if any double is NaN, the result is NaN

不仅更快、更短,而且更简单。

可选的主要目的是表示函数的

流的基本专门化的目的是避免装箱/拆箱开销。对于
optionant
和friends,存在不可避免的装箱级别(如果它们不存在,情况会更糟,因为另一种选择是
Optional
),但其目的是让处理返回值的人立即取消装箱(或者提供默认值,或者在不存在时抛出异常)然后再处理实际的原语


支持所有额外的API在可选原语上执行算术、比较等操作会增加更多API膨胀。使用它会导致代码混乱、速度慢,与Java中已经存在的完美的算术表达式语法相比,这是一个相当大的缺点。简而言之,在可选原语上添加一系列操作被认为是没有用的。

可选#映射
似乎需要一个
函数
,而不是
二进制运算符
,因此它只适用于在一个值上操作的函数,不是像
add
multiply
这样的东西。我一直在使用helper方法,但我真的不明白他们为什么省略这些方法,或者至少不理解添加它们的能力。请注意,像
OptionalDouble
这样的原语的
Optional
类是
final
,因此它们甚至不能被扩展。@siki它们是final的,因为Optional是不可变的类,因此永远不应该被扩展,既然你不能再保证不变性了,那么如果一个方法把一个
optionaldough
作为参数。@ajb我说过类似的话。IE:
可选选项=。。。;opt=opt.map(d->d*2)@siki它们无法扩展,但您可以单独实现,并提供从一个转换到另一个的方法。这不是最干净的解决方案,但会奏效。