Подтвердить что ты не робот

Есть ли эквивалент Scala Либо в Java 8?

Точно так же, как java.util.Optional<T> в Java 8 (несколько) эквивалентно типу Scala Option[T], существует ли эквивалент Scala Either[L, R]?

4b9b3361

Ответ 1

Нет типа 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) в начале обоих методов factory. Точно так же можно было бы добавить поддержку пустого либо.

Ответ 2

Смотрите Atlassian Fugue. Существует хорошая реализация Either.

Ответ 3

В стандартной библиотеке Java нет ни одного. Однако существует Either в FunctionalJava, а также многие другие классные классы.

Ответ 4

На момент написания статьи vavr (ранее javaslang), вероятно, является самой популярной функциональной библиотекой Java 8. Это похоже на лямбда-компаньон. Или в другом ответе.

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

Ответ 5

lambda-companion имеет тип 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())

Ответ 6

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.

  • раскрытие Я являюсь автором реакции циклопов.

Ответ 7

Нет, нет.

Разработчики Java-языка явно заявляют, что такие типы, как Option<T>, предназначены для использования только как временные значения (например, в результатах операций потока), поэтому, хотя они такие же, как на других языках, они не должны использоваться поскольку они используются на других языках. Поэтому неудивительно, что нет такой вещи, как Either, потому что она не возникает естественным образом (например, из потоков), например Optional.

Ответ 8

Существует отдельная реализация Either в небольшой библиотеке, "ambivalence": http://github.com/poetix/ambivalence

Вы можете получить его от центра Maven:

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