在Java 8中是否有相当于Scala的Ayno?
就像在Java 8中(在某种程度上)等同于Scala的类型一样,是否存在与Scala的等效类型?java.util.Optional<T>
Option[T]
Either[L, R]
就像在Java 8中(在某种程度上)等同于Scala的类型一样,是否存在与Scala的等效类型?java.util.Optional<T>
Option[T]
Either[L, R]
没有类型是Java 8,所以你需要自己创建一个或使用一些第三方库。Either
您可以使用新类型构建这样的功能(但请阅读本答案的末尾):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; };
}
}
很容易将其更改为严格拒绝,只需在两种工厂方法的开头插入 a 即可。同样,添加对空的支持也是可以想象的。null
Objects.requireNonNull(value)
在撰写本文时,vavr(以前称为javaslang)可能是最流行的Java 8函数库。它与我的另一个答案中的lambda-companion的Any非常相似。
Either<String,Integer> value = compute().right().map(i -> i * 2).toEither();