在 Java 8 中是否有与 Scala 的任何等价物?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26162407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 01:56:10  来源:igfitidea点击:

Is there an equivalent of Scala's Either in Java 8?

javascalajava-8

提问by HRJ

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.util.Optional<T>在 Java 8 中(有点)等价于 Scala 的Option[T]类型一样,是否有等价于 Scala 的类型Either[L, R]

采纳答案by Holger

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

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

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

您可以使用新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);
    }
}

Example use case:

示例用例:

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));}
));

In retrospective, the Optionalbased solution is more like an academic example, but not a recommended approach. One problem is the treatment of nullas “empty” which contradicts the meaning of “either”.

回想起来,Optional基于解决方案更像是一个学术示例,而不是推荐的方法。一个问题是null“空”的处理,这与“要么”的含义相矛盾。

The following code shows an Eitherthat considers nulla possible value, so it's strictly “either”, left or right, even if the value is 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; };
    }
}

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

null通过简单地Objects.requireNonNull(value)在两个工厂方法的开头插入一个,很容易将其更改为严格拒绝。同样,可以想象添加对空值的支持。

回答by Vladimir Matveev

No, there is none.

不,没有。

Java language developers explicitly state that types like Option<T>are intended to be used only as temporary values (e.g. in stream operations results), so while they arethe same thing as in other languages, they are not supposedto be used as they are used in other languages. So it is not surprising that there is no such thing as Eitherbecause it does not arise naturally (e.g. from stream operations) like Optionaldoes.

Java 语言开发人员明确声明,like 类型Option<T>仅用作临时值(例如在流操作结果中),因此虽然它们与其他语言的相同,但不应像在其他语言中那样使用它们语言。因此,没有这样的事情并不奇怪,Either因为它不像自然发生(例如从流操作)Optional

回答by Ravi Kiran

There is no Either in the Java Standard Library. However there is an implementation of Eitherin FunctionalJava, along with many other nice classes.

Java 标准库中没有任何一个。然而,在FunctionalJava 中有一个That的实现,以及许多其他不错的类。

回答by ZhekaKozlov

See Atlassian Fugue. There is a good implementation of Eitherthere.

参见Atlassian Fugue。那里有一个很好的实现Either

回答by Dominic Fox

There is a stand-alone implementation of Eitherin a small library, "ambivalence": http://github.com/poetix/ambivalence

Either在一个小库中有一个独立的实现,“矛盾”:http: //github.com/poetix/ambivalence

You can get it from Maven central:

您可以从 Maven 中心获取它:

<dependency>
    <groupId>com.codepoetics</groupId>
    <artifactId>ambivalence</artifactId>
    <version>0.2</version>
</dependency>

回答by whirlwin

lambda-companionhas an Eithertype (and a few other functional types e.g. Try)

lambda-companion有一个Either类型(和一些其他的函数类型,例如Try

<dependency>
    <groupId>no.finn.lambda</groupId>
    <artifactId>lambda-companion</artifactId>
    <version>0.25</version>
</dependency>

Using it is easy:

使用它很容易:

final String myValue = Either.right("example").fold(failure -> handleFailure(failure), Function.identity())

回答by whirlwin

At the time of writing, vavr(formerly javaslang) is probably the most popular functional Java 8 library. It is pretty similar to lambda-companion's Either in my other answer.

在撰写本文时,vavr(以前称为 javaslang)可能是最受欢迎的 Java 8 函数库。它与我的另一个答案中的 lambda-companion 非常相似。

Either<String,Integer> value = compute().right().map(i -> i * 2).toEither();

回答by John McClean

cyclops-reacthas a 'right' biased either implementation called Xor.

cyclops-react有一个“正确”的偏向任一实现,称为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

There is also a related type Iorwhich can act as an either or a tuple2.

还有一个相关的类型Ior的可作为任一或tuple2行动。

  • disclosure I am the author of cyclops-react.
  • 披露我是独眼巨人反应的作者。