Реактивные расширения для 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)
Довольно круто?