簡體   English   中英

在 Java 8 中是否有與 Scala 的任何等價物?

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

就像 Java 8 java.util.Optional<T>是(有點)等價於 Scala 的Option[T]類型,是否有等價於 Scala 的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視為“空”,這與“要么”的含義相矛盾。

下面的代碼顯示了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 同樣,添加對空的支持也是可以想象的。

在撰寫本文時, vavr (以前稱為 javaslang)可能是最受歡迎的 Java 8 函數庫。 它與我的另一個答案中的 lambda-companion 非常相似。

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

Atlassian Fugue 這是一個很好的實施Either在那里。

Java 標准庫中沒有任何一個。 然而,在FunctionalJava 中有一個That的實現,以及許多其他不錯的類。

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

還有一個相關的類型Ior的可作為任一或tuple2行動。

  • 披露我是獨眼巨人反應的作者。

不,沒有。

Java 語言開發人員明確聲明像Option<T>這樣的類型僅用作臨時值(例如在流操作結果中),因此雖然它們與其他語言的相同,但它們不應該被用作它們用於其他語言。 因此,沒有Either這樣的東西並不奇怪,因為它不像Optional那樣自然產生(例如來自流操作)。

有一個獨立的實現Either在一個小型圖書館,“矛盾”: http://github.com/poetix/ambivalence

您可以從 Maven 中心獲取它:

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

λ-伴侶具有Either類型(和其他一些功能類型例如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())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM