SlideShare a Scribd company logo
1 of 81
Download to read offline
RxJava Applied:
Concise Examples where It Shines
Igor Lozynskyi
JavaDay Kyiv - Oct 14-15, 2016
Software Engineer at GlobalLogic
Presentation’s home
https://github.com/aigor/rx-presentation
Outline
● RxJava vs Java 8 Streams
● RxJava usage example
Pre Java 8 data processing
interface Iterator<T> {
T next();
boolean hasNext();
void remove();
}
Pre Java 8 data processing
List<Employee> employees = service.getEmployees();
Map<Integer, List<Employee>> ageDistribution = new HashMap<>();
for (Employee employee : employees) {
if (employee.getAge() > 25){
List<Employee> thisAge = ageDistribution.get(employee.getAge());
if (thisAge != null){
thisAge.add(employee);
} else{
List<Employee> createThisAge = new ArrayList<>();
createThisAge.add(employee);
ageDistribution.put(employee.getAge(), createThisAge);
}
}
}
System.out.println(ageDistribution);
Java 8 Stream ...
● Connects data source and client
● Do not hold any data
● Implements map / filter / reduce pattern
● Enforces functional style of data processing
Stream collectors
List<Employee> employees = service.getEmployees();
Map<Integer, List<Employee>> ageDistribution = new HashMap<>();
for (Employee employee : employees) {
if (employee.getAge() > 25) {
List<Employee> thisAge = ageDistribution.get(employee.getAge());
if (thisAge != null){
thisAge.add(employee);
} else {
List<Employee> createThisAge = new ArrayList<>();
createThisAge.add(employee);
ageDistribution.put(employee.getAge(), createThisAge);
}
}
}
System.out.println(ageDistribution);
Stream collectors
List<Employee> employees = service.getEmployees();
Map<Integer, List<Employee>> ageDistribution =
employees.stream()
.filter(e -> e.getAge() > 25)
.collect(Collectors.groupingBy(Employee::getAge));
System.out.println(ageDistribution);
Stream collectors
List<Employee> employees = service.getEmployees();
Map<Integer, Long> ageDistribution =
employees.stream()
.filter(e -> e.getAge() > 25)
.collect(Collectors.groupingBy(
Employee::getAge,
Collectors.counting()
));
Stream sources
Stream<String> stream1 = Arrays.asList("A", "B").stream();
Stream<String> stream2 = Stream.of("Q", "P", "R");
IntStream chars = "some text".chars();
Stream<String> words
= Pattern.compile(" ").splitAsStream("some other text");
Non-standard stream sources
Can we use non-standard stream sources?
?
Stream generator
Stream
.generate(() -> UUID.randomUUID().toString())
.limit(4)
.forEach(System.out::println);
Spliterator interface
public interface Spliterator<T> {
boolean tryAdvance(Consumer<? super T> action);
Spliterator<T> trySplit();
long estimateSize();
int characteristics();
}
class RandomSpliterator implements Spliterator<String> {
public boolean tryAdvance(Consumer<? super String> action) {
action.accept(UUID.randomUUID().toString());
return true;
}
// for parallel streams
public Spliterator<String> trySplit() {
return null;
}
public long estimateSize() { return Long.MAX_VALUE; };
public int characteristics() { return NONNULL | DISTINCT; }
}
Generate sequence: 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, ...
IntStream sequence =
IntStream.rangeClosed(1, 50)
.flatMap(i ->
IntStream.iterate(i, identity()).limit(i)
);
sequence.forEach(System.out::println);
Stream API is powerful!
Stream API - async processing
getEmployeeIds().stream()
.map(this::doHttpRequest)
.collect(Collectors.toList())
Output:
[main] processing request: c677c497
[main] processing request: 3b5320a9
[main] processing request: 9248b92e
[main] processing request: 97a68a53
Stream API - async processing
getEmployeeIds().stream()
.parallel()
.map(this::doHttpRequest)
.collect(Collectors.toList())
Output:
[main] processing request: 7674da72
[ForkJoinPool.commonPool-worker-2] processing request: 747ae948
[ForkJoinPool.commonPool-worker-1] processing request: 33fe0bac
[ForkJoinPool.commonPool-worker-3] processing request: 812f69f3
[main] processing request: 11dda466
[ForkJoinPool.commonPool-worker-2] processing request: 12e22a10
[ForkJoinPool.commonPool-worker-1] processing request: e2b324f9
[ForkJoinPool.commonPool-worker-3] processing request: 8f9f8a97
Stream API - async processing
ForkJoinPool forkJoinPool = new ForkJoinPool(80);
forkJoinPool.submit(() ->
getEmployeeIds().stream()
.parallel()
.map(this::doHttpRequest)
.collect(Collectors.toList())
).get();
Stream API has some limitations
Reactive Streams: what the difference
RxJava
http://reactivex.io
https://github.com/ReactiveX/RxJava
17,700 stars on GitHub
Short history
● From 2009 for .NET
● From 2013 for JVM (latest: 1.2.1, Oct 5, 2016)
● Now a lot of other languages
RxJava Observer
interface Observer<T> {
void onNext(T t);
void onCompleted();
void onError(Throwable e);
}
RxJava Subscription
interface Subscription {
void unsubscribe();
boolean isUnsubscribed();
}
Observable
● Central class in RxJava library
● It’s big: ~ 10k lines of code (with comments)
● It’s complex: ~ 100 static methods, ~ 150 non-static
Subscription sub =
Observable
.create(s -> {
s.onNext("A");
s.onNext("B");
s.onCompleted();
})
.subscribe(m -> log.info("Message received: " + m),
e -> log.warning("Error: " + e.getMessage()),
() -> log.info("Done!"));
Output:
Message received: A
Message received: B
Done!
Observable<Integer> empty = Observable.empty();
Observable<Integer> never = Observable.never();
Observable<Integer> error = Observable.error(exception);
Observable useful for tests
never() - never emit anything (no data, no errors)
public static <T, Resource> Observable<T> using(
final Func0<Resource> resourceFactory,
final Func1<Resource, Observable<T>> observableFactory,
final Action1<Resource> disposeAction
){ }
Observable from resource
Observable
.from(Arrays.asList(1, 2, 5, 7, 8, 12, 3, 6, 7, 8))
.filter(i -> (i > 3 && i < 8))
.forEach(System.out::println);
Output:
5
7
6
7
Marble diagram: filter
Marble diagram: last
Marble diagram: reduce
Marble diagram: buffer
Marble diagram: timer
Marble diagram: interval
Time series
Observable<Long> timer = Observable.timer(2, TimeUnit.SECONDS);
Observable<Long> interval = Observable.interval(1, TimeUnit.SECONDS);
timer.forEach(System.out::println);
interval.forEach(System.out::println);
Output:
Process finished with exit code 0
Time series
Observable<Long> timer = Observable.timer(2, TimeUnit.SECONDS);
Observable<Long> interval = Observable.interval(1, TimeUnit.SECONDS);
timer.forEach(i -> System.out.println(currentThread().getName() + " - " + i));
interval.forEach(i -> System.out.println(currentThread().getName() + " - " + i));
Output:
RxComputationThreadPool-2 - 0
RxComputationThreadPool-1 - 0
RxComputationThreadPool-2 - 1
Process finished with exit code 0
Thread.sleep(2000);
Schedulers
public final class Schedulers {
public static Scheduler immediate() {...}
public static Scheduler trampoline() {...}
public static Scheduler newThread() {...}
public static Scheduler computation() {...}
public static Scheduler io() {...}
public static TestScheduler test() {...}
public static Scheduler from(Executor executor) {...}
}
Schedulers
Observable.from("one", "two", "three", "four", "five")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(/* an Observer */);
Marble diagram: merge
Merge
Observable<Integer> odds = Observable
.just(1, 3, 5).subscribeOn(Schedulers.io());
Observable<Integer> evens = Observable.just(2, 4, 6);
Observable.merge(odds, evens)
.subscribe(
System.out::println,
System.err::println,
() -> System.out.println("Finished"));
Marble diagram: zip
Zip
Observable<String> odds = Observable.just("A", "B", "C", "D");
Observable<Integer> evens = Observable.just(2, 4, 6);
Observable.zip(odds, evens, (a, b) -> a + "-" + b)
.subscribe(
System.out::println,
System.err::println,
() -> System.out.println("Finished"));
Output:
A-2
B-4
C-6
Finished
Cold & Hot Observables
● Cold Observable emits events only having subscriber
● Hot Observable emits events even without subscribers
Backpressure
Backpressure
Backpreasure is a way to slow down emission of elements
It can act on observing side
Strategies:
● Buffering items (buffer, window)
● Skipping items (sampling, throttling, etc)
● Request for specific number of elements
Backpressure: request for elements
public interface Producer {
void request(long n);
}
Stream API vs RxJava
RxJava:
● allows to process data in chosen thread, this is useful for IO,
computations, specialized threads (GUI threads),
● allows synchronization on clocks and application events,
● works in push mode, producer initiates data transfer, but consumer may
control data flow via backpressure.
Stream API:
● tuned for hot data processing,
● good for parallel computation,
● has rich set of collectors for data.
Shakespeare Plays Scrabble Benchmark (throughput)
Non-Parallel Streams 44.995 ± 1.718 ms/op
Parallel Streams 14.095 ± 0.616 ms/op
RxJava 310.378 ± 9.688 ms/op
RxJava (2.0.0-RC4) 156.334 ± 8.423 ms/op
Performance
Based on JMH benchmark by Jose Paumard
Scenarios where RxJava shines
● Observables are better callbacks (easily wrap callbacks)
● Observables are highly composable (on contrast with callbacks)
● Provide async stream of data (on contrast with CompletableFuture)
● Observables can handle errors (have retry / backup strategies)
● Give complete control over running threads
● Good for managing IO rich application workflows
● Perfect for Android development (no Java 8 required, retrolambda compatible)
● Netflix uses RxJava for most their internal APIs
Request flow
Created with draw.io
Stream API and RxJava are friends!
You can easily build Observable from Stream
Iterator<T> iterator = ...;
Observable<T> observable = Observable.from(() -> iterator);
You can map Observable to Stream by implementing adapter
public static<T> Iterator<T> of(Observable<? extends T> ob){
class Adapter implements Iterator<T>, Consumer<T> {
...
}
return new Adapter();
}
External libraries that work with RxJava
● hystrix - latency and fault tolerance bulkheading library
● camel RX - to reuse Apache Camel components
● rxjava-http-tail - allows you to follow logs over HTTP
● mod-rxvertx - extension for VertX that provides support Rx
● rxjava-jdbc - use RxJava with JDBC to stream ResultSets
● rtree - immutable in-memory R-tree and R*-tree with RxJava
● and many more ...
RxJava is not new
JDeferred
CompletableFuture<T>
Scala.Rx
Scala Actors
Spring Integration
What’s around?
● Google Agera - reactive streams for Android by Google
● Project Reactor - flow API implementation by Pivotal & Spring
● Akka-Streams - Akka based streams
● Monix - Scala based implementation of Reactive Streams
● Vert.x, Lagom - if you want more than streams
Let’s build something with RxJava
Use case: Stream of tweets
Created with Balsamiq Mockups
Twitter API
Twitter Stream API (WebSocket alike):
● Doc: https://dev.twitter.com/streaming/overview
● Library: com.twitter:hbc-core:2.2.0
Twitter REST API:
● GET https://api.twitter.com/1.1/users/show.json?screen_name=jeeconf
● GET https://api.twitter.com/1.1/search/tweets.json?q=from:jeeconf
Let’s look at entities
class Tweet {
String text;
int favorite_count;
String author;
int author_followers;
}
class Profile {
String screen_name;
String name;
String location;
int statuses_count;
int followers_count;
}
class UserWithTweet {
Profile profile;
Tweet tweet;
}
Marble diagram
Profile getUserProfile(String screenName) {
ObjectMapper om = new ObjectMapper();
return (Profile) om.readValue(om.readTree(
Unirest.get(API_BASE_URL + "users/show.json")
.queryString("screen_name", screenName)
.header("Authorization", bearerAuth(authToken.get()))
.asString()
.getBody()),
Profile.class);
}
Get user profile synchronously
Get user profile asynchronously
Observable<Profile> getUserProfile(String screenName) {
return Observable.fromCallable(() -> {
ObjectMapper om = new ObjectMapper();
return (Profile) om.readValue(om.readTree(
Unirest.get(API_BASE_URL + "users/show.json")
.queryString("screen_name", screenName)
.header("Authorization", bearerAuth(authToken.get()))
.asString()
.getBody()),
Profile.class);
});
}
Add some errors handling
Observable<Profile> getUserProfile(String screenName) {
if (authToken.isPresent()) {
return Observable.fromCallable(() -> {
ObjectMapper om = new ObjectMapper();
return (Profile) om.readValue(om.readTree(
Unirest.get(API_BASE_URL + "users/show.json")
.queryString("screen_name", screenName)
.header("Authorization", bearerAuth(authToken.get()))
.asString()
.getBody()),
Profile.class);
}).doOnCompleted(() -> log("getUserProfile completed for: " + screenName));
} else {
return Observable.error(new RuntimeException("Can not connect to twitter"));
}
}
Let’s do something concurrently
Illustration: Arsenal Firearms S.r.l.
Get data concurrently
Observable<UserWithTweet> getUserAndPopularTweet(String author){
return Observable.just(author)
.flatMap(u -> {
Observable<Profile> profile = client.getUserProfile(u)
.subscribeOn(Schedulers.io());
Observable<Tweet> tweet = client.getUserRecentTweets(u)
.defaultIfEmpty(null)
.reduce((t1, t2) ->
t1.retweet_count > t2.retweet_count ? t1 : t2)
.subscribeOn(Schedulers.io());
return Observable.zip(profile, tweet, UserWithTweet::new);
});
}
Let’s subscribe on stream of tweets!
streamClient.getStream("RxJava", "JavaDay", "Java")
streamClient.getStream("RxJava", "JavaDay", "Java", "Trump", "Hillary")
streamClient.getStream("RxJava", "JavaDay", "Java", "Trump", "Hillary")
.distinctUntilChanged()
.map(p -> p.author)
.flatMap(name -> getUserAndPopularTweet(name))
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.immediate())
.subscribe(p -> log.info("The most popular tweet of user "
+ p.profile.name + ": " + p.tweet));
.scan((u1, u2) -> u1.author_followers > u2.author_followers ? u1 : u2)
streamClient.getStream("RxJava", "JavaDay", "Java", "Trump")
.scan((u1, u2) -> u1.author_followers > u2.author_followers ? u1 : u2)
.distinctUntilChanged()
.map(p -> p.author)
.flatMap(name -> {
Observable<Profile> profile = client.getUserProfile(name)
.subscribeOn(Schedulers.io());
Observable<Tweet> tweet = client.getUserRecentTweets(name)
.defaultIfEmpty(null)
.reduce((t1, t2) ->
t1.retweet_count > t2.retweet_count ? t1 : t2)
.subscribeOn(Schedulers.io());
return Observable.zip(profile, tweet, UserWithTweet::new);
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.immediate())
.subscribe(p -> log.info("The most popular tweet of user "
+ p.profile.name + ": " + p.tweet));
Marble diagram
@Test public void correctlyJoinsHttpResults() throws Exception {
String testUser = "testUser";
Profile profile = new Profile("u1", "Name", "USA", 10, 20, 30);
Tweet tweet1 = new Tweet("text-1", 10, 20, testUser, 30);
Tweet tweet2 = new Tweet("text-2", 40, 50, testUser, 30);
TwitterClient client = mock(TwitterClient.class);
when(client.getUserProfile(testUser)).thenReturn(Observable.just(profile));
when(client.getUserRecentTweets(testUser)).thenReturn(Observable.just(tweet1, tweet2));
TestSubscriber<UserWithTweet> testSubscriber = new TestSubscriber<>();
new Solutions().getUserAndPopularTweet(client, testUser).subscribe(testSubscriber);
testSubscriber.awaitTerminalEvent();
assertEquals(singletonList(new UserWithTweet(profile, tweet2)),
testSubscriber.getOnNextEvents());
}
Don’t believe it works?
● API is big (150+ methods to remember)
● Requires to understand underlying magic
● Hard to debug
● Don’t forget about back pressure
Conclusions: pitfalls
● It is functional, it is reactive*
● Good for integration scenarios
● Allows to control execution threads
● Easy to compose workflows
● Easy to integrate into existing solutions
● Easy Ok to test
* RxJava is inspired by FRP (Functional Reactive Programming), but doesn’t implement it
Conclusions: strength
● RxJava 2.0 in few weeks!
● RxJava 2.0 is better and faster
● RxJava 2.0 is Java 9 Flow API compatible
● We will see more and more reactive streams
Conclusions: future
Q&A
https://github.com/aigor/rx-presentation
Thanks
Presentation template by SlidesCarnival
@siromaha
aigooor@gmail.com

More Related Content

What's hot

Reactive programming with RxJava
Reactive programming with RxJavaReactive programming with RxJava
Reactive programming with RxJavaJobaer Chowdhury
 
Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for AndroidTomáš Kypta
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on AndroidTomáš Kypta
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaFrank Lyaruu
 
The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016Frank Lyaruu
 
Functional Reactive Programming in Clojurescript
Functional Reactive Programming in ClojurescriptFunctional Reactive Programming in Clojurescript
Functional Reactive Programming in ClojurescriptLeonardo Borges
 
Reactive Programming on Android - RxAndroid - RxJava
Reactive Programming on Android - RxAndroid - RxJavaReactive Programming on Android - RxAndroid - RxJava
Reactive Programming on Android - RxAndroid - RxJavaAli Muzaffar
 
Streams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to RxStreams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to RxAndrzej Sitek
 
RxJava 2.0 介紹
RxJava 2.0 介紹RxJava 2.0 介紹
RxJava 2.0 介紹Kros Huang
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaKros Huang
 
Reactive programming with RxAndroid
Reactive programming with RxAndroidReactive programming with RxAndroid
Reactive programming with RxAndroidSavvycom Savvycom
 
Reactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaReactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaKasun Indrasiri
 
Real world functional reactive programming
Real world functional reactive programmingReal world functional reactive programming
Real world functional reactive programmingEric Polerecky
 
JavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good PartsJavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good PartsKonrad Malawski
 
RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015Constantine Mars
 

What's hot (20)

Introduction to Reactive Java
Introduction to Reactive JavaIntroduction to Reactive Java
Introduction to Reactive Java
 
Reactive programming with RxJava
Reactive programming with RxJavaReactive programming with RxJava
Reactive programming with RxJava
 
Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for Android
 
Reactive Java (GeeCON 2014)
Reactive Java (GeeCON 2014)Reactive Java (GeeCON 2014)
Reactive Java (GeeCON 2014)
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
rx-java-presentation
rx-java-presentationrx-java-presentation
rx-java-presentation
 
The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016
 
Functional Reactive Programming in Clojurescript
Functional Reactive Programming in ClojurescriptFunctional Reactive Programming in Clojurescript
Functional Reactive Programming in Clojurescript
 
Reactive Programming on Android - RxAndroid - RxJava
Reactive Programming on Android - RxAndroid - RxJavaReactive Programming on Android - RxAndroid - RxJava
Reactive Programming on Android - RxAndroid - RxJava
 
Streams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to RxStreams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to Rx
 
RxJava in practice
RxJava in practice RxJava in practice
RxJava in practice
 
RxJava 2.0 介紹
RxJava 2.0 介紹RxJava 2.0 介紹
RxJava 2.0 介紹
 
Rx java in action
Rx java in actionRx java in action
Rx java in action
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJava
 
Reactive programming with RxAndroid
Reactive programming with RxAndroidReactive programming with RxAndroid
Reactive programming with RxAndroid
 
Reactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaReactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-Java
 
Real world functional reactive programming
Real world functional reactive programmingReal world functional reactive programming
Real world functional reactive programming
 
JavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good PartsJavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good Parts
 
RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015
 

Viewers also liked

Reactive Thinking in Java
Reactive Thinking in JavaReactive Thinking in Java
Reactive Thinking in JavaYakov Fain
 
Issues in knowledge representation
Issues in knowledge representationIssues in knowledge representation
Issues in knowledge representationSravanthi Emani
 
Intro to Graph Databases Using Tinkerpop, TitanDB, and Gremlin
Intro to Graph Databases Using Tinkerpop, TitanDB, and GremlinIntro to Graph Databases Using Tinkerpop, TitanDB, and Gremlin
Intro to Graph Databases Using Tinkerpop, TitanDB, and GremlinCaleb Jones
 
Knowledge representation in AI
Knowledge representation in AIKnowledge representation in AI
Knowledge representation in AIVishal Singh
 
Knowledge representation and Predicate logic
Knowledge representation and Predicate logicKnowledge representation and Predicate logic
Knowledge representation and Predicate logicAmey Kerkar
 
Introduction to Machine Learning
Introduction to Machine LearningIntroduction to Machine Learning
Introduction to Machine LearningRahul Jain
 

Viewers also liked (7)

Reactive Thinking in Java
Reactive Thinking in JavaReactive Thinking in Java
Reactive Thinking in Java
 
04 pig data operations
04 pig data operations04 pig data operations
04 pig data operations
 
Issues in knowledge representation
Issues in knowledge representationIssues in knowledge representation
Issues in knowledge representation
 
Intro to Graph Databases Using Tinkerpop, TitanDB, and Gremlin
Intro to Graph Databases Using Tinkerpop, TitanDB, and GremlinIntro to Graph Databases Using Tinkerpop, TitanDB, and Gremlin
Intro to Graph Databases Using Tinkerpop, TitanDB, and Gremlin
 
Knowledge representation in AI
Knowledge representation in AIKnowledge representation in AI
Knowledge representation in AI
 
Knowledge representation and Predicate logic
Knowledge representation and Predicate logicKnowledge representation and Predicate logic
Knowledge representation and Predicate logic
 
Introduction to Machine Learning
Introduction to Machine LearningIntroduction to Machine Learning
Introduction to Machine Learning
 

Similar to RxJava Applied: Concise Examples where It Shines

Developing streaming applications with apache apex (strata + hadoop world)
Developing streaming applications with apache apex (strata + hadoop world)Developing streaming applications with apache apex (strata + hadoop world)
Developing streaming applications with apache apex (strata + hadoop world)Apache Apex
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기NAVER D2
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomyDongmin Yu
 
Javaone 2016 : Supercharge your (reactive) Streams
Javaone 2016 : Supercharge your (reactive) StreamsJavaone 2016 : Supercharge your (reactive) Streams
Javaone 2016 : Supercharge your (reactive) StreamsJohn McClean
 
A Deep Dive into Query Execution Engine of Spark SQL
A Deep Dive into Query Execution Engine of Spark SQLA Deep Dive into Query Execution Engine of Spark SQL
A Deep Dive into Query Execution Engine of Spark SQLDatabricks
 
Flink 0.10 @ Bay Area Meetup (October 2015)
Flink 0.10 @ Bay Area Meetup (October 2015)Flink 0.10 @ Bay Area Meetup (October 2015)
Flink 0.10 @ Bay Area Meetup (October 2015)Stephan Ewen
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestPavan Chitumalla
 
Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014hezamu
 
Where the wild things are - Benchmarking and Micro-Optimisations
Where the wild things are - Benchmarking and Micro-OptimisationsWhere the wild things are - Benchmarking and Micro-Optimisations
Where the wild things are - Benchmarking and Micro-OptimisationsMatt Warren
 
PgQ Generic high-performance queue for PostgreSQL
PgQ Generic high-performance queue for PostgreSQLPgQ Generic high-performance queue for PostgreSQL
PgQ Generic high-performance queue for PostgreSQLelliando dias
 
JS Fest 2019. Anjana Vakil. Serverless Bebop
JS Fest 2019. Anjana Vakil. Serverless BebopJS Fest 2019. Anjana Vakil. Serverless Bebop
JS Fest 2019. Anjana Vakil. Serverless BebopJSFestUA
 
GDG DevFest 2015 - Reactive approach for slowpokes
GDG DevFest 2015 - Reactive approach for slowpokesGDG DevFest 2015 - Reactive approach for slowpokes
GDG DevFest 2015 - Reactive approach for slowpokesSergey Tarasevich
 
What is new in java 8 concurrency
What is new in java 8 concurrencyWhat is new in java 8 concurrency
What is new in java 8 concurrencykshanth2101
 
Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Fabio Collini
 
How to Think in RxJava Before Reacting
How to Think in RxJava Before ReactingHow to Think in RxJava Before Reacting
How to Think in RxJava Before ReactingIndicThreads
 
Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0Anyscale
 
[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data productIgor Lozynskyi
 
Realtime Statistics based on Apache Storm and RocketMQ
Realtime Statistics based on Apache Storm and RocketMQRealtime Statistics based on Apache Storm and RocketMQ
Realtime Statistics based on Apache Storm and RocketMQXin Wang
 
Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨flyinweb
 

Similar to RxJava Applied: Concise Examples where It Shines (20)

Developing streaming applications with apache apex (strata + hadoop world)
Developing streaming applications with apache apex (strata + hadoop world)Developing streaming applications with apache apex (strata + hadoop world)
Developing streaming applications with apache apex (strata + hadoop world)
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomy
 
Javaone 2016 : Supercharge your (reactive) Streams
Javaone 2016 : Supercharge your (reactive) StreamsJavaone 2016 : Supercharge your (reactive) Streams
Javaone 2016 : Supercharge your (reactive) Streams
 
A Deep Dive into Query Execution Engine of Spark SQL
A Deep Dive into Query Execution Engine of Spark SQLA Deep Dive into Query Execution Engine of Spark SQL
A Deep Dive into Query Execution Engine of Spark SQL
 
Flink 0.10 @ Bay Area Meetup (October 2015)
Flink 0.10 @ Bay Area Meetup (October 2015)Flink 0.10 @ Bay Area Meetup (October 2015)
Flink 0.10 @ Bay Area Meetup (October 2015)
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014
 
Where the wild things are - Benchmarking and Micro-Optimisations
Where the wild things are - Benchmarking and Micro-OptimisationsWhere the wild things are - Benchmarking and Micro-Optimisations
Where the wild things are - Benchmarking and Micro-Optimisations
 
PgQ Generic high-performance queue for PostgreSQL
PgQ Generic high-performance queue for PostgreSQLPgQ Generic high-performance queue for PostgreSQL
PgQ Generic high-performance queue for PostgreSQL
 
JS Fest 2019. Anjana Vakil. Serverless Bebop
JS Fest 2019. Anjana Vakil. Serverless BebopJS Fest 2019. Anjana Vakil. Serverless Bebop
JS Fest 2019. Anjana Vakil. Serverless Bebop
 
GDG DevFest 2015 - Reactive approach for slowpokes
GDG DevFest 2015 - Reactive approach for slowpokesGDG DevFest 2015 - Reactive approach for slowpokes
GDG DevFest 2015 - Reactive approach for slowpokes
 
What is new in java 8 concurrency
What is new in java 8 concurrencyWhat is new in java 8 concurrency
What is new in java 8 concurrency
 
Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2
 
How to Think in RxJava Before Reacting
How to Think in RxJava Before ReactingHow to Think in RxJava Before Reacting
How to Think in RxJava Before Reacting
 
Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0
 
[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product
 
Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 
Realtime Statistics based on Apache Storm and RocketMQ
Realtime Statistics based on Apache Storm and RocketMQRealtime Statistics based on Apache Storm and RocketMQ
Realtime Statistics based on Apache Storm and RocketMQ
 
Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨
 

Recently uploaded

Alper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentAlper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentInMediaRes1
 
AMERICAN LANGUAGE HUB_Level2_Student'sBook_Answerkey.pdf
AMERICAN LANGUAGE HUB_Level2_Student'sBook_Answerkey.pdfAMERICAN LANGUAGE HUB_Level2_Student'sBook_Answerkey.pdf
AMERICAN LANGUAGE HUB_Level2_Student'sBook_Answerkey.pdfphamnguyenenglishnb
 
Solving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptxSolving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptxOH TEIK BIN
 
Introduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher EducationIntroduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher Educationpboyjonauth
 
Influencing policy (training slides from Fast Track Impact)
Influencing policy (training slides from Fast Track Impact)Influencing policy (training slides from Fast Track Impact)
Influencing policy (training slides from Fast Track Impact)Mark Reed
 
How to do quick user assign in kanban in Odoo 17 ERP
How to do quick user assign in kanban in Odoo 17 ERPHow to do quick user assign in kanban in Odoo 17 ERP
How to do quick user assign in kanban in Odoo 17 ERPCeline George
 
ACC 2024 Chronicles. Cardiology. Exam.pdf
ACC 2024 Chronicles. Cardiology. Exam.pdfACC 2024 Chronicles. Cardiology. Exam.pdf
ACC 2024 Chronicles. Cardiology. Exam.pdfSpandanaRallapalli
 
Difference Between Search & Browse Methods in Odoo 17
Difference Between Search & Browse Methods in Odoo 17Difference Between Search & Browse Methods in Odoo 17
Difference Between Search & Browse Methods in Odoo 17Celine George
 
Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17Celine George
 
Gas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxGas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxDr.Ibrahim Hassaan
 
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTiammrhaywood
 
Framing an Appropriate Research Question 6b9b26d93da94caf993c038d9efcdedb.pdf
Framing an Appropriate Research Question 6b9b26d93da94caf993c038d9efcdedb.pdfFraming an Appropriate Research Question 6b9b26d93da94caf993c038d9efcdedb.pdf
Framing an Appropriate Research Question 6b9b26d93da94caf993c038d9efcdedb.pdfUjwalaBharambe
 
Employee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxEmployee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxNirmalaLoungPoorunde1
 
What is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPWhat is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPCeline George
 
ROOT CAUSE ANALYSIS PowerPoint Presentation
ROOT CAUSE ANALYSIS PowerPoint PresentationROOT CAUSE ANALYSIS PowerPoint Presentation
ROOT CAUSE ANALYSIS PowerPoint PresentationAadityaSharma884161
 
Crayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon ACrayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon AUnboundStockton
 

Recently uploaded (20)

Alper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentAlper Gobel In Media Res Media Component
Alper Gobel In Media Res Media Component
 
AMERICAN LANGUAGE HUB_Level2_Student'sBook_Answerkey.pdf
AMERICAN LANGUAGE HUB_Level2_Student'sBook_Answerkey.pdfAMERICAN LANGUAGE HUB_Level2_Student'sBook_Answerkey.pdf
AMERICAN LANGUAGE HUB_Level2_Student'sBook_Answerkey.pdf
 
Solving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptxSolving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptx
 
Introduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher EducationIntroduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher Education
 
9953330565 Low Rate Call Girls In Rohini Delhi NCR
9953330565 Low Rate Call Girls In Rohini  Delhi NCR9953330565 Low Rate Call Girls In Rohini  Delhi NCR
9953330565 Low Rate Call Girls In Rohini Delhi NCR
 
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdfTataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
 
Influencing policy (training slides from Fast Track Impact)
Influencing policy (training slides from Fast Track Impact)Influencing policy (training slides from Fast Track Impact)
Influencing policy (training slides from Fast Track Impact)
 
How to do quick user assign in kanban in Odoo 17 ERP
How to do quick user assign in kanban in Odoo 17 ERPHow to do quick user assign in kanban in Odoo 17 ERP
How to do quick user assign in kanban in Odoo 17 ERP
 
ACC 2024 Chronicles. Cardiology. Exam.pdf
ACC 2024 Chronicles. Cardiology. Exam.pdfACC 2024 Chronicles. Cardiology. Exam.pdf
ACC 2024 Chronicles. Cardiology. Exam.pdf
 
Rapple "Scholarly Communications and the Sustainable Development Goals"
Rapple "Scholarly Communications and the Sustainable Development Goals"Rapple "Scholarly Communications and the Sustainable Development Goals"
Rapple "Scholarly Communications and the Sustainable Development Goals"
 
Difference Between Search & Browse Methods in Odoo 17
Difference Between Search & Browse Methods in Odoo 17Difference Between Search & Browse Methods in Odoo 17
Difference Between Search & Browse Methods in Odoo 17
 
Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17
 
Gas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxGas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptx
 
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
 
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
 
Framing an Appropriate Research Question 6b9b26d93da94caf993c038d9efcdedb.pdf
Framing an Appropriate Research Question 6b9b26d93da94caf993c038d9efcdedb.pdfFraming an Appropriate Research Question 6b9b26d93da94caf993c038d9efcdedb.pdf
Framing an Appropriate Research Question 6b9b26d93da94caf993c038d9efcdedb.pdf
 
Employee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxEmployee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptx
 
What is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPWhat is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERP
 
ROOT CAUSE ANALYSIS PowerPoint Presentation
ROOT CAUSE ANALYSIS PowerPoint PresentationROOT CAUSE ANALYSIS PowerPoint Presentation
ROOT CAUSE ANALYSIS PowerPoint Presentation
 
Crayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon ACrayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon A
 

RxJava Applied: Concise Examples where It Shines

  • 1. RxJava Applied: Concise Examples where It Shines Igor Lozynskyi JavaDay Kyiv - Oct 14-15, 2016 Software Engineer at GlobalLogic
  • 3. Outline ● RxJava vs Java 8 Streams ● RxJava usage example
  • 4. Pre Java 8 data processing interface Iterator<T> { T next(); boolean hasNext(); void remove(); }
  • 5. Pre Java 8 data processing List<Employee> employees = service.getEmployees(); Map<Integer, List<Employee>> ageDistribution = new HashMap<>(); for (Employee employee : employees) { if (employee.getAge() > 25){ List<Employee> thisAge = ageDistribution.get(employee.getAge()); if (thisAge != null){ thisAge.add(employee); } else{ List<Employee> createThisAge = new ArrayList<>(); createThisAge.add(employee); ageDistribution.put(employee.getAge(), createThisAge); } } } System.out.println(ageDistribution);
  • 6. Java 8 Stream ... ● Connects data source and client ● Do not hold any data ● Implements map / filter / reduce pattern ● Enforces functional style of data processing
  • 7. Stream collectors List<Employee> employees = service.getEmployees(); Map<Integer, List<Employee>> ageDistribution = new HashMap<>(); for (Employee employee : employees) { if (employee.getAge() > 25) { List<Employee> thisAge = ageDistribution.get(employee.getAge()); if (thisAge != null){ thisAge.add(employee); } else { List<Employee> createThisAge = new ArrayList<>(); createThisAge.add(employee); ageDistribution.put(employee.getAge(), createThisAge); } } } System.out.println(ageDistribution);
  • 8. Stream collectors List<Employee> employees = service.getEmployees(); Map<Integer, List<Employee>> ageDistribution = employees.stream() .filter(e -> e.getAge() > 25) .collect(Collectors.groupingBy(Employee::getAge)); System.out.println(ageDistribution);
  • 9. Stream collectors List<Employee> employees = service.getEmployees(); Map<Integer, Long> ageDistribution = employees.stream() .filter(e -> e.getAge() > 25) .collect(Collectors.groupingBy( Employee::getAge, Collectors.counting() ));
  • 10. Stream sources Stream<String> stream1 = Arrays.asList("A", "B").stream(); Stream<String> stream2 = Stream.of("Q", "P", "R"); IntStream chars = "some text".chars(); Stream<String> words = Pattern.compile(" ").splitAsStream("some other text");
  • 11. Non-standard stream sources Can we use non-standard stream sources? ?
  • 12. Stream generator Stream .generate(() -> UUID.randomUUID().toString()) .limit(4) .forEach(System.out::println);
  • 13. Spliterator interface public interface Spliterator<T> { boolean tryAdvance(Consumer<? super T> action); Spliterator<T> trySplit(); long estimateSize(); int characteristics(); }
  • 14. class RandomSpliterator implements Spliterator<String> { public boolean tryAdvance(Consumer<? super String> action) { action.accept(UUID.randomUUID().toString()); return true; } // for parallel streams public Spliterator<String> trySplit() { return null; } public long estimateSize() { return Long.MAX_VALUE; }; public int characteristics() { return NONNULL | DISTINCT; } }
  • 15. Generate sequence: 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, ... IntStream sequence = IntStream.rangeClosed(1, 50) .flatMap(i -> IntStream.iterate(i, identity()).limit(i) ); sequence.forEach(System.out::println);
  • 16. Stream API is powerful!
  • 17. Stream API - async processing getEmployeeIds().stream() .map(this::doHttpRequest) .collect(Collectors.toList()) Output: [main] processing request: c677c497 [main] processing request: 3b5320a9 [main] processing request: 9248b92e [main] processing request: 97a68a53
  • 18. Stream API - async processing getEmployeeIds().stream() .parallel() .map(this::doHttpRequest) .collect(Collectors.toList()) Output: [main] processing request: 7674da72 [ForkJoinPool.commonPool-worker-2] processing request: 747ae948 [ForkJoinPool.commonPool-worker-1] processing request: 33fe0bac [ForkJoinPool.commonPool-worker-3] processing request: 812f69f3 [main] processing request: 11dda466 [ForkJoinPool.commonPool-worker-2] processing request: 12e22a10 [ForkJoinPool.commonPool-worker-1] processing request: e2b324f9 [ForkJoinPool.commonPool-worker-3] processing request: 8f9f8a97
  • 19. Stream API - async processing ForkJoinPool forkJoinPool = new ForkJoinPool(80); forkJoinPool.submit(() -> getEmployeeIds().stream() .parallel() .map(this::doHttpRequest) .collect(Collectors.toList()) ).get();
  • 20. Stream API has some limitations
  • 21. Reactive Streams: what the difference
  • 23. Short history ● From 2009 for .NET ● From 2013 for JVM (latest: 1.2.1, Oct 5, 2016) ● Now a lot of other languages
  • 24. RxJava Observer interface Observer<T> { void onNext(T t); void onCompleted(); void onError(Throwable e); }
  • 25. RxJava Subscription interface Subscription { void unsubscribe(); boolean isUnsubscribed(); }
  • 26. Observable ● Central class in RxJava library ● It’s big: ~ 10k lines of code (with comments) ● It’s complex: ~ 100 static methods, ~ 150 non-static
  • 27. Subscription sub = Observable .create(s -> { s.onNext("A"); s.onNext("B"); s.onCompleted(); }) .subscribe(m -> log.info("Message received: " + m), e -> log.warning("Error: " + e.getMessage()), () -> log.info("Done!")); Output: Message received: A Message received: B Done!
  • 28. Observable<Integer> empty = Observable.empty(); Observable<Integer> never = Observable.never(); Observable<Integer> error = Observable.error(exception); Observable useful for tests never() - never emit anything (no data, no errors)
  • 29. public static <T, Resource> Observable<T> using( final Func0<Resource> resourceFactory, final Func1<Resource, Observable<T>> observableFactory, final Action1<Resource> disposeAction ){ } Observable from resource
  • 30. Observable .from(Arrays.asList(1, 2, 5, 7, 8, 12, 3, 6, 7, 8)) .filter(i -> (i > 3 && i < 8)) .forEach(System.out::println); Output: 5 7 6 7
  • 37. Time series Observable<Long> timer = Observable.timer(2, TimeUnit.SECONDS); Observable<Long> interval = Observable.interval(1, TimeUnit.SECONDS); timer.forEach(System.out::println); interval.forEach(System.out::println); Output: Process finished with exit code 0
  • 38. Time series Observable<Long> timer = Observable.timer(2, TimeUnit.SECONDS); Observable<Long> interval = Observable.interval(1, TimeUnit.SECONDS); timer.forEach(i -> System.out.println(currentThread().getName() + " - " + i)); interval.forEach(i -> System.out.println(currentThread().getName() + " - " + i)); Output: RxComputationThreadPool-2 - 0 RxComputationThreadPool-1 - 0 RxComputationThreadPool-2 - 1 Process finished with exit code 0 Thread.sleep(2000);
  • 39. Schedulers public final class Schedulers { public static Scheduler immediate() {...} public static Scheduler trampoline() {...} public static Scheduler newThread() {...} public static Scheduler computation() {...} public static Scheduler io() {...} public static TestScheduler test() {...} public static Scheduler from(Executor executor) {...} }
  • 40. Schedulers Observable.from("one", "two", "three", "four", "five") .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(/* an Observer */);
  • 42. Merge Observable<Integer> odds = Observable .just(1, 3, 5).subscribeOn(Schedulers.io()); Observable<Integer> evens = Observable.just(2, 4, 6); Observable.merge(odds, evens) .subscribe( System.out::println, System.err::println, () -> System.out.println("Finished"));
  • 44. Zip Observable<String> odds = Observable.just("A", "B", "C", "D"); Observable<Integer> evens = Observable.just(2, 4, 6); Observable.zip(odds, evens, (a, b) -> a + "-" + b) .subscribe( System.out::println, System.err::println, () -> System.out.println("Finished")); Output: A-2 B-4 C-6 Finished
  • 45. Cold & Hot Observables ● Cold Observable emits events only having subscriber ● Hot Observable emits events even without subscribers
  • 47. Backpressure Backpreasure is a way to slow down emission of elements It can act on observing side Strategies: ● Buffering items (buffer, window) ● Skipping items (sampling, throttling, etc) ● Request for specific number of elements
  • 48. Backpressure: request for elements public interface Producer { void request(long n); }
  • 49. Stream API vs RxJava RxJava: ● allows to process data in chosen thread, this is useful for IO, computations, specialized threads (GUI threads), ● allows synchronization on clocks and application events, ● works in push mode, producer initiates data transfer, but consumer may control data flow via backpressure. Stream API: ● tuned for hot data processing, ● good for parallel computation, ● has rich set of collectors for data.
  • 50. Shakespeare Plays Scrabble Benchmark (throughput) Non-Parallel Streams 44.995 ± 1.718 ms/op Parallel Streams 14.095 ± 0.616 ms/op RxJava 310.378 ± 9.688 ms/op RxJava (2.0.0-RC4) 156.334 ± 8.423 ms/op Performance Based on JMH benchmark by Jose Paumard
  • 51. Scenarios where RxJava shines ● Observables are better callbacks (easily wrap callbacks) ● Observables are highly composable (on contrast with callbacks) ● Provide async stream of data (on contrast with CompletableFuture) ● Observables can handle errors (have retry / backup strategies) ● Give complete control over running threads ● Good for managing IO rich application workflows ● Perfect for Android development (no Java 8 required, retrolambda compatible) ● Netflix uses RxJava for most their internal APIs
  • 53. Stream API and RxJava are friends! You can easily build Observable from Stream Iterator<T> iterator = ...; Observable<T> observable = Observable.from(() -> iterator); You can map Observable to Stream by implementing adapter public static<T> Iterator<T> of(Observable<? extends T> ob){ class Adapter implements Iterator<T>, Consumer<T> { ... } return new Adapter(); }
  • 54. External libraries that work with RxJava ● hystrix - latency and fault tolerance bulkheading library ● camel RX - to reuse Apache Camel components ● rxjava-http-tail - allows you to follow logs over HTTP ● mod-rxvertx - extension for VertX that provides support Rx ● rxjava-jdbc - use RxJava with JDBC to stream ResultSets ● rtree - immutable in-memory R-tree and R*-tree with RxJava ● and many more ...
  • 55. RxJava is not new JDeferred CompletableFuture<T> Scala.Rx Scala Actors Spring Integration
  • 56. What’s around? ● Google Agera - reactive streams for Android by Google ● Project Reactor - flow API implementation by Pivotal & Spring ● Akka-Streams - Akka based streams ● Monix - Scala based implementation of Reactive Streams ● Vert.x, Lagom - if you want more than streams
  • 57. Let’s build something with RxJava
  • 58. Use case: Stream of tweets Created with Balsamiq Mockups
  • 59. Twitter API Twitter Stream API (WebSocket alike): ● Doc: https://dev.twitter.com/streaming/overview ● Library: com.twitter:hbc-core:2.2.0 Twitter REST API: ● GET https://api.twitter.com/1.1/users/show.json?screen_name=jeeconf ● GET https://api.twitter.com/1.1/search/tweets.json?q=from:jeeconf
  • 60. Let’s look at entities class Tweet { String text; int favorite_count; String author; int author_followers; } class Profile { String screen_name; String name; String location; int statuses_count; int followers_count; } class UserWithTweet { Profile profile; Tweet tweet; }
  • 62. Profile getUserProfile(String screenName) { ObjectMapper om = new ObjectMapper(); return (Profile) om.readValue(om.readTree( Unirest.get(API_BASE_URL + "users/show.json") .queryString("screen_name", screenName) .header("Authorization", bearerAuth(authToken.get())) .asString() .getBody()), Profile.class); } Get user profile synchronously
  • 63. Get user profile asynchronously Observable<Profile> getUserProfile(String screenName) { return Observable.fromCallable(() -> { ObjectMapper om = new ObjectMapper(); return (Profile) om.readValue(om.readTree( Unirest.get(API_BASE_URL + "users/show.json") .queryString("screen_name", screenName) .header("Authorization", bearerAuth(authToken.get())) .asString() .getBody()), Profile.class); }); }
  • 64. Add some errors handling Observable<Profile> getUserProfile(String screenName) { if (authToken.isPresent()) { return Observable.fromCallable(() -> { ObjectMapper om = new ObjectMapper(); return (Profile) om.readValue(om.readTree( Unirest.get(API_BASE_URL + "users/show.json") .queryString("screen_name", screenName) .header("Authorization", bearerAuth(authToken.get())) .asString() .getBody()), Profile.class); }).doOnCompleted(() -> log("getUserProfile completed for: " + screenName)); } else { return Observable.error(new RuntimeException("Can not connect to twitter")); } }
  • 65. Let’s do something concurrently Illustration: Arsenal Firearms S.r.l.
  • 66.
  • 67. Get data concurrently Observable<UserWithTweet> getUserAndPopularTweet(String author){ return Observable.just(author) .flatMap(u -> { Observable<Profile> profile = client.getUserProfile(u) .subscribeOn(Schedulers.io()); Observable<Tweet> tweet = client.getUserRecentTweets(u) .defaultIfEmpty(null) .reduce((t1, t2) -> t1.retweet_count > t2.retweet_count ? t1 : t2) .subscribeOn(Schedulers.io()); return Observable.zip(profile, tweet, UserWithTweet::new); }); }
  • 68.
  • 69. Let’s subscribe on stream of tweets!
  • 72. streamClient.getStream("RxJava", "JavaDay", "Java", "Trump", "Hillary") .distinctUntilChanged() .map(p -> p.author) .flatMap(name -> getUserAndPopularTweet(name)) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.immediate()) .subscribe(p -> log.info("The most popular tweet of user " + p.profile.name + ": " + p.tweet)); .scan((u1, u2) -> u1.author_followers > u2.author_followers ? u1 : u2)
  • 73. streamClient.getStream("RxJava", "JavaDay", "Java", "Trump") .scan((u1, u2) -> u1.author_followers > u2.author_followers ? u1 : u2) .distinctUntilChanged() .map(p -> p.author) .flatMap(name -> { Observable<Profile> profile = client.getUserProfile(name) .subscribeOn(Schedulers.io()); Observable<Tweet> tweet = client.getUserRecentTweets(name) .defaultIfEmpty(null) .reduce((t1, t2) -> t1.retweet_count > t2.retweet_count ? t1 : t2) .subscribeOn(Schedulers.io()); return Observable.zip(profile, tweet, UserWithTweet::new); }) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.immediate()) .subscribe(p -> log.info("The most popular tweet of user " + p.profile.name + ": " + p.tweet));
  • 75. @Test public void correctlyJoinsHttpResults() throws Exception { String testUser = "testUser"; Profile profile = new Profile("u1", "Name", "USA", 10, 20, 30); Tweet tweet1 = new Tweet("text-1", 10, 20, testUser, 30); Tweet tweet2 = new Tweet("text-2", 40, 50, testUser, 30); TwitterClient client = mock(TwitterClient.class); when(client.getUserProfile(testUser)).thenReturn(Observable.just(profile)); when(client.getUserRecentTweets(testUser)).thenReturn(Observable.just(tweet1, tweet2)); TestSubscriber<UserWithTweet> testSubscriber = new TestSubscriber<>(); new Solutions().getUserAndPopularTweet(client, testUser).subscribe(testSubscriber); testSubscriber.awaitTerminalEvent(); assertEquals(singletonList(new UserWithTweet(profile, tweet2)), testSubscriber.getOnNextEvents()); }
  • 77. ● API is big (150+ methods to remember) ● Requires to understand underlying magic ● Hard to debug ● Don’t forget about back pressure Conclusions: pitfalls
  • 78. ● It is functional, it is reactive* ● Good for integration scenarios ● Allows to control execution threads ● Easy to compose workflows ● Easy to integrate into existing solutions ● Easy Ok to test * RxJava is inspired by FRP (Functional Reactive Programming), but doesn’t implement it Conclusions: strength
  • 79. ● RxJava 2.0 in few weeks! ● RxJava 2.0 is better and faster ● RxJava 2.0 is Java 9 Flow API compatible ● We will see more and more reactive streams Conclusions: future
  • 81. Thanks Presentation template by SlidesCarnival @siromaha aigooor@gmail.com