在Java 8中是否有相当于Scala的Either? [英] Is there an equivalent of Scala's Either in Java 8?

查看:81
本文介绍了在Java 8中是否有相当于Scala的Either?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就像 Java 8中的java.util.Optional< T> (有些)相当于Scala的选项[T] 类型,是否相当于Scala的要么[L,R]

Just like java.util.Optional<T> in Java 8 is (somewhat) equivalent to Scala's Option[T] type, is there an equivalent to Scala's Either[L, R]?

推荐答案

没有要么类型是Java 8,所以你需要自己创建一个或使用一些第三方库。

There is no Either type is Java 8, so you need to create one yourself or use some third-party library.

您可以使用新的可选类型构建此类功能(但请阅读此答案的末尾):

You may build such a feature using the new Optional type (but read to the end of this answer):

final class Either<L,R>
{
    public static <L,R> Either<L,R> left(L value) {
        return new Either<>(Optional.of(value), Optional.empty());
    }
    public static <L,R> Either<L,R> right(R value) {
        return new Either<>(Optional.empty(), Optional.of(value));
    }
    private final Optional<L> left;
    private final Optional<R> right;
    private Either(Optional<L> l, Optional<R> r) {
      left=l;
      right=r;
    }
    public <T> T map(
        Function<? super L, ? extends T> lFunc,
        Function<? super R, ? extends T> rFunc)
    {
        return left.<T>map(lFunc).orElseGet(()->right.map(rFunc).get());
    }
    public <T> Either<T,R> mapLeft(Function<? super L, ? extends T> lFunc)
    {
        return new Either<>(left.map(lFunc),right);
    }
    public <T> Either<L,T> mapRight(Function<? super R, ? extends T> rFunc)
    {
        return new Either<>(left, right.map(rFunc));
    }
    public void apply(Consumer<? super L> lFunc, Consumer<? super R> rFunc)
    {
        left.ifPresent(lFunc);
        right.ifPresent(rFunc);
    }
}

示例用例:

new Random().ints(20, 0, 2).mapToObj(i -> (Either<String,Integer>)(i==0?
  Either.left("left value (String)"):
  Either.right(42)))
.forEach(either->either.apply(
  left ->{ System.out.println("received left value: "+left.substring(11));},
  right->{ System.out.println("received right value: 0x"+Integer.toHexString(right));}
));

在回顾展中,基于可选的解决方案是更像是一个学术的例子,但不是推荐的方法。一个问题是将 null 视为空,这与任一的含义相矛盾。

In retrospective, the Optional based solution is more like an academic example, but not a recommended approach. One problem is the treatment of null as "empty" which contradicts the meaning of "either".

以下代码显示要么认为 null 一个可能的值,所以它严格左右,左或右,即使值为 null

The following code shows an Either that considers null a possible value, so it’s strictly "either", left or right, even if the value is null:

abstract class Either<L,R>
{
    public static <L,R> Either<L,R> left(L value) {
        return new Either<L,R>() {
            @Override public <T> T map(Function<? super L, ? extends T> lFunc,
                                       Function<? super R, ? extends T> rFunc) {
                return lFunc.apply(value);
            }
        };
    }
    public static <L,R> Either<L,R> right(R value) {
        return new Either<L,R>() {
            @Override public <T> T map(Function<? super L, ? extends T> lFunc,
                                       Function<? super R, ? extends T> rFunc) {
                return rFunc.apply(value);
            }

        };
    }
    private Either() {}
    public abstract <T> T map(
      Function<? super L, ? extends T> lFunc, Function<? super R, ? extends T> rFunc);

    public <T> Either<T,R> mapLeft(Function<? super L, ? extends T> lFunc) {
        return this.<Either<T,R>>map(t -> left(lFunc.apply(t)), t -> (Either<T,R>)this);
    }
    public <T> Either<L,T> mapRight(Function<? super R, ? extends T> lFunc) {
        return this.<Either<L,T>>map(t -> (Either<L,T>)this, t -> right(lFunc.apply(t)));
    }
    public void apply(Consumer<? super L> lFunc, Consumer<? super R> rFunc) {
        map(consume(lFunc), consume(rFunc));
    }
    private <T> Function<T,Void> consume(Consumer<T> c) {
        return t -> { c.accept(t); return null; };
    }
}

很容易将其改为严格拒绝 null 只需在两个工厂方法的开头插入 Objects.requireNonNull(value)即可。同样,添加对空的支持也是可以想象的。

It’s easy to change that to a strict rejection of null by simply inserting an Objects.requireNonNull(value) at the beginning of both factory methods. Likewise, adding support for an empty either would be imaginable.

这篇关于在Java 8中是否有相当于Scala的Either?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆