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

A Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformA Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformChameera Dedduwage
 
1029 - Danh muc Sach Giao Khoa 10 . pdf
1029 -  Danh muc Sach Giao Khoa 10 . pdf1029 -  Danh muc Sach Giao Khoa 10 . pdf
1029 - Danh muc Sach Giao Khoa 10 . pdfQucHHunhnh
 
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...christianmathematics
 
Arihant handbook biology for class 11 .pdf
Arihant handbook biology for class 11 .pdfArihant handbook biology for class 11 .pdf
Arihant handbook biology for class 11 .pdfchloefrazer622
 
The basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptxThe basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptxheathfieldcps1
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfsanyamsingh5019
 
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...Krashi Coaching
 
Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)eniolaolutunde
 
General AI for Medical Educators April 2024
General AI for Medical Educators April 2024General AI for Medical Educators April 2024
General AI for Medical Educators April 2024Janet Corral
 
Holdier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdfHoldier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdfagholdier
 
Introduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsIntroduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsTechSoup
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdfQucHHunhnh
 
social pharmacy d-pharm 1st year by Pragati K. Mahajan
social pharmacy d-pharm 1st year by Pragati K. Mahajansocial pharmacy d-pharm 1st year by Pragati K. Mahajan
social pharmacy d-pharm 1st year by Pragati K. Mahajanpragatimahajan3
 
Class 11th Physics NEET formula sheet pdf
Class 11th Physics NEET formula sheet pdfClass 11th Physics NEET formula sheet pdf
Class 11th Physics NEET formula sheet pdfAyushMahapatra5
 
Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..Disha Kariya
 
Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111Sapana Sha
 

Recently uploaded (20)

A Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformA Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy Reform
 
1029 - Danh muc Sach Giao Khoa 10 . pdf
1029 -  Danh muc Sach Giao Khoa 10 . pdf1029 -  Danh muc Sach Giao Khoa 10 . pdf
1029 - Danh muc Sach Giao Khoa 10 . pdf
 
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
 
Advance Mobile Application Development class 07
Advance Mobile Application Development class 07Advance Mobile Application Development class 07
Advance Mobile Application Development class 07
 
Arihant handbook biology for class 11 .pdf
Arihant handbook biology for class 11 .pdfArihant handbook biology for class 11 .pdf
Arihant handbook biology for class 11 .pdf
 
The basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptxThe basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptx
 
Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"
Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"
Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"
 
Mattingly "AI & Prompt Design: The Basics of Prompt Design"
Mattingly "AI & Prompt Design: The Basics of Prompt Design"Mattingly "AI & Prompt Design: The Basics of Prompt Design"
Mattingly "AI & Prompt Design: The Basics of Prompt Design"
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdf
 
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
 
Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)
 
General AI for Medical Educators April 2024
General AI for Medical Educators April 2024General AI for Medical Educators April 2024
General AI for Medical Educators April 2024
 
Holdier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdfHoldier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdf
 
Introduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsIntroduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The Basics
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdf
 
INDIA QUIZ 2024 RLAC DELHI UNIVERSITY.pptx
INDIA QUIZ 2024 RLAC DELHI UNIVERSITY.pptxINDIA QUIZ 2024 RLAC DELHI UNIVERSITY.pptx
INDIA QUIZ 2024 RLAC DELHI UNIVERSITY.pptx
 
social pharmacy d-pharm 1st year by Pragati K. Mahajan
social pharmacy d-pharm 1st year by Pragati K. Mahajansocial pharmacy d-pharm 1st year by Pragati K. Mahajan
social pharmacy d-pharm 1st year by Pragati K. Mahajan
 
Class 11th Physics NEET formula sheet pdf
Class 11th Physics NEET formula sheet pdfClass 11th Physics NEET formula sheet pdf
Class 11th Physics NEET formula sheet pdf
 
Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..
 
Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111
 

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