在Java 8中是否有相当于Scala的呢?
就像Java 8 java.util.Optional<T>
有点类似于Scala的Option[T]
types,是否有相当于Scala的Either[L, R]
?
没有Either
types的Java 8,所以你需要自己创build一个或使用一些第三方库。
您可以使用新的Optional
types来构build这样的function(但是可以阅读本答案的结尾):
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
的解决scheme更像是一个学术的例子,但不是推荐的方法。 一个问题是把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; }; } }
只需在两个工厂方法的开头插入一个Objects.requireNonNull(value)
,就可以很容易地将其改为null
。 同样,增加对空的支持也是可以想象的。
见Atlassian赋格 。 那里有一个很好的实现。
在Java标准库中没有任何一个。 然而,在FunctionalJava中还有一个实现,以及许多其他很好的类。
在撰写本文时, javaslang可能是最受欢迎的function性Java 8库。 这与lambda-companion的非常相似,在我的其他答案。
Either<String,Integer> value = compute().right().map(i -> i * 2).toEither();
lambda伴侣有一个Either
types(和一些其他functiontypes,例如Try
)
<dependency> <groupId>no.finn.lambda</groupId> <artifactId>lambda-companion</artifactId> <version>0.25</version> </dependency>
使用它很容易:
final String myValue = Either.right("example").fold(failure -> handleFailure(failure), Function.identity())
不,没有。
Java语言开发人员明确指出像Option<T>
这样的types只能用作临时值(例如在stream操作结果中),所以尽pipe它们与其他语言中的相同,但它们不应该被用作用于其他语言。 所以不存在这样的事情就不足为奇了,因为它不像Optional
那样是自然产生的(例如从stream操作)。
独眼巨人反应有一个“正确的”偏见或称Xor的实施。
Xor.primary("hello") .map(s->s+" world") //Primary["hello world"] Xor.secondary("hello") .map(s->s+" world") //Secondary["hello"] Xor.secondary("hello") .swap() .map(s->s+" world") //Primary["hello world"] Xor.accumulateSecondary(ListX.of(Xor.secondary("failed1"), Xor.secondary("failed2"), Xor.primary("success")), Semigroups.stringConcat) //failed1failed2
还有一个相关的typesIor可以作为一个元组或者一个元组2。
- 披露我是独眼巨人反应的作者。
在小型图书馆中有一个独立的实现:“矛盾”: http : //github.com/poetix/ambivalence
你可以从Maven central得到它:
<dependency> <groupId>com.codepoetics</groupId> <artifactId>ambivalence</artifactId> <version>0.2</version> </dependency>