Java 8에 Scala의 Either와 동등한 것이 있습니까?
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; };
}
}
It’s easy to change that to a strict rejection of null
by simply inserting an Objects.requireNonNull(value)
at the beginning of both factory methods. Likewise, adding support for an empty either would be imaginable.
See Atlassian Fugue. There is a good implementation of Either
there.
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.
Either<String,Integer> value = compute().right().map(i -> i * 2).toEither();
There is no Either in the Java Standard Library. However there is an implementation of Either in FunctionalJava, along with many other nice classes.
cyclops-react has a 'right' biased either implementation called 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 Ior which can act as an either or a tuple2.
- disclosure I am the author of cyclops-react.
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 are the same thing as in other languages, they are not supposed to be used as they are used in other languages. So it is not surprising that there is no such thing as Either
because it does not arise naturally (e.g. from stream operations) like Optional
does.
lambda-companion has an Either
type (and a few other functional types e.g. 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())
There is a stand-alone implementation of Either
in a small library, "ambivalence": http://github.com/poetix/ambivalence
You can get it from Maven central:
<dependency>
<groupId>com.codepoetics</groupId>
<artifactId>ambivalence</artifactId>
<version>0.2</version>
</dependency>
참고URL : https://stackoverflow.com/questions/26162407/is-there-an-equivalent-of-scalas-either-in-java-8
'developer tip' 카테고리의 다른 글
PC로 iPad Safari 디버그 (0) | 2020.11.14 |
---|---|
동적 ArrayList 항목 유형이있는 Gson TypeToken (0) | 2020.11.14 |
Homebrew는 nvm을 설치하지만 나중에 nvm을 찾을 수 없습니까? (0) | 2020.11.14 |
Keycloak의 OAuth2 / OpenID Connect 엔드 포인트는 무엇입니까? (0) | 2020.11.14 |
Visual Studio에서 '웹 사이트'와 '프로젝트'의 차이점 (0) | 2020.11.14 |