[java] Java 8에 Scala의 Either와 동등한 것이 있습니까?

java.util.Optional<T>Java 8에서 (다소) Scala의 Option[T]유형 과 동등한 것처럼 Scala의 유형과 동등한 것이 Either[L, R]있습니까?



답변

EitherJava 8은 유형 이 없으므로 직접 작성하거나 타사 라이브러리를 사용해야합니다.

새로운 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; };
    }
}

두 팩토리 메서드의 시작 부분 null에를 삽입하기 만하면 엄격한 거부로 쉽게 변경할 수 Objects.requireNonNull(value)있습니다. 마찬가지로, 빈 둘 중 하나에 대한 지원을 추가하는 것은 상상할 수 있습니다.


답변

글을 쓰는 시점에서 vavr (이전의 javaslang)은 아마도 가장 인기있는 기능적 Java 8 라이브러리 일 것입니다. 내 다른 대답에서 lambda-companion의 Either와 매우 유사합니다.

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


답변

Atlassian Fugue를 참조하십시오 . 거기에 좋은 구현이 Either있습니다.


답변

Java Standard Library에는 Either가 없습니다. 그러나의 구현이 하나FunctionalJava 다른 많은 좋은 클래스와 함께이.


답변

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

둘 중 하나 또는 튜플 2 역할을 할 수 있는 관련 유형 Ior 도 있습니다.

  • 공개 저는 cyclops-react의 저자입니다.


답변

아니요, 없습니다.

종류가 좋아하는 것이 자바 개발자가 명시 적으로 상태 Option<T>임시 값으로 사용하기위한 것입니다 (예를 들어 스트림 작업 결과에), 그들이 그렇게하는 동안 있습니다 다른 언어로 같은 것을, 그들이하는 그들은 다른에 사용되는로 사용하기 언어. 따라서 Either자연적으로 발생하지 않기 때문에 (예 : 스트림 작업에서) 발생하는 것과 같은 것이 없다는 것은 놀라운 일 이 아닙니다 Optional.


답변

Either작은 라이브러리에 “ambivalence”라는 독립 실행 형 구현이 있습니다 : http://github.com/poetix/ambivalence

Maven 중앙에서 가져올 수 있습니다.

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