Реактивные расширения для Java

Есть ли эквивалент Reactive Extensions (.NET) для Java?

О Rx (Reactive Extensions)

Rx - это библиотека для составления асинхронных и основанных на событиях программ с использованием наблюдаемых коллекций.

Мне известны механизмы правил, такие как Drools от JBOSS, но есть ли другой способ, который ближе к Microsoft.NET подходит?

Ответ 1

Я не знаю одного - и, откровенно говоря, это было бы трудно сделать таким аккуратным способом. Сторона резьбы хорошо; Java отлично работает, когда дело доходит до потоковой передачи... но на данный момент язык просто не поддерживает соответствующие функции.

Одна из опрятных конструктивных особенностей LINQ заключается в том, что все основано на интерфейсах, а затем методы расширения используются для добавления дополнительных функций. Это позволяет свободно читать код - представьте, нужно ли писать:

IObservable<int> = Observable.Select(
                       Observable.Where(
                           source, x => x.SomeCondition)
                       x => x.SomeProjection);

Ик. Метод расширения намного более изящный:

IObservable<int> = source.Where(x => x.SomeCondition)
                         .Select(x => x.SomeProjection);

Теперь версия Java может быть основана на абстрактном базовом классе, но это потеряет часть элегантности.

Далее появятся лямбда-выражения и преобразования групп методов - они действительно являются фундаментальными для LINQ в целом; самый близкий эквивалент в Java (анонимные внутренние классы) слишком уродливы, чтобы их можно было использовать везде, где вы бы использовали лямбда-выражение в С#.

В принципе, Java-версия Rx была бы осуществима, но она не была бы столь же изящной, как версия С#, и, вероятно, поэтому она не была выполнена, насколько мне известно. Для Java могут быть другие библиотеки, основанные на асинхронности, но они вряд ли будут такими же всеобъемлющими и опрятными, как Rx.

Возможно, изменения в Java 7 сделают это более осуществимым; насколько я знаю, методы расширения не вводятся, но абстрактная версия базового класса была бы разумной, если синтаксис лямбда окажется в порядке...

Ответ 2

В соответствии с этим сообщением NetFlix они портировали Rx на Java. Похоже, что он пока недоступен, но у них есть история выпуска таких встроенных в инструмент инструментов как с открытым исходным кодом, поэтому я ожидаю, что он будет выпущен в конце концов.

Ответ 3

Если вы все еще заинтересованы, я в последнее время работаю над Java-библиотекой, которая предлагает большинство операторов Rx на реактивной и интерактивной сторона также.

Это определенно не так хорошо, как .NET. Java не имеет методов расширения или типов функций, поэтому все должно вызываться через статический метод и внутренние классы. В .NET:

Observable.Range(0, 10).SelectMany(
    o => Observable.Range(0, o)
).Run(Console.WriteLine);

Моя библиотека:

Reactive.run(
    Reactive.selectMany(
        Reactive.range(0, 10), 
        new Func1<Observable<Integer>, Integer>() {
            public Observable<Integer> invoke(Integer param1) {
               return Reactive.range(0, param1);
        }
    }       
), Reactive.println());

Interactive.run(
    Interactive.selectMany(
        Interactive.range(0, 10), 
        new Func1<Iterable<Integer>, Integer>() {
            public Iterable<Integer> invoke(Integer param1) {
               return Interactive.range(0, param1);
        }
    }       
), Interactive.println());

Я использую типы Func0, Func1, Func2 для lambdas и Closeable для отмены регистрации. После того, как Java получит гражданскую функцию первого класса, эти типы FuncX можно просто заменить. Closeable может использоваться улучшением Java-try-with-resources. Третья уродство объясняется слабым умозаключением в разных местах.

Ответ 4

Вы можете рассмотреть перенос raix (wiki), написанный на ActionScript 3, на Java 7, когда он поступит. Проект (мой собственный) является открытым исходным кодом и включает в себя тесты блочного модуля .NET-версии фреймворка для обеспечения совместимости.

Подобно Java, AS3 не поддерживает ни методы расширения, ни лямбда-выражения, поэтому реализация может быть аналогичной. Сказав это, вам нужно быть осторожным с условиями гонки, поскольку AVM не поддерживает потоки, поэтому в RxAs нет кода блокировки.

Ответ 5

RxJava (RX, портированный Netflix) доступен и стабилен здесь: https://github.com/ReactiveX/RxJava.

Он даже хорошо работает с синтаксисом лямбда Java 8! Вы можете делать такие вещи:

Observable
  .from(Arrays.asList(1, 2, 3, 4, 5))
  .filter(val -> val % 2 == 0)
  .map(val -> val * val)
  .scan(0, (prev, curr) -> prev + curr)
  .subscribe(System.out::println)

Довольно круто?