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