在Java 8中是否有相当于Scala的呢?

就像Java 8 java.util.Optional<T>有点类似于Scala的Option[T]types,是否有相当于Scala的Either[L, R]

没有Eithertypes的Java 8,所以你需要自己创build一个或使用一些第三方库。

您可以使用新的Optionaltypes来构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看作是“空的”,这与“两者”的含义相矛盾。

下面的代码显示了Eithernull视为可能值的方法,所以即使值为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伴侣有一个Eithertypes(和一些其他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>