EitherJava 8 没有类型,因此您需要自己创建一个或使用一些第三方库。
您可以使用新
Optional类型来构建这样的功能(但请阅读此答案的结尾):
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));}));回顾起来,
Optional基于基础的解决方案更像是一个学术实例,而不是推荐的方法。一个问题是对
null“空” 的处理,这与“任一个”的含义相矛盾。
以下代码显示了一个
Either考虑
null可能值的,因此即使值是,它也严格是“左右”(左或右)
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)在两个工厂方法的开头插入,就很容易将其更改为严格拒绝。同样,可以想象增加对空容器的支持。



