package com.dockerx.reactive.rxjava; import com.google.common.collect.ImmutableList; import io.reactivex.Observable; import io.reactivex.ObservableOperator; import io.reactivex.ObservableTransformer; import io.reactivex.functions.Action; import io.reactivex.observers.DisposableObserver; import io.reactivex.subjects.PublishSubject; import org.junit.jupiter.api.Test; import java.math.BigInteger; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; import static io.reactivex.Observable.interval; /** * @author Author 知秋 * @email [email protected] * @time Created by Auser on 2018/1/25 5:30. */ public class OperatorsTest<T> { private static void log(Object msg) { System.out.println( Thread.currentThread().getName() + ": " + msg); } static void sleep(int timeout, TimeUnit unit) { try { unit.sleep(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } @Test void filter_test() { String[] monthArray = {"Jan", "Feb", "Mar", "Apl", "Maly", "Jun", "July", "Aug", "Sept", "Oct", "Nov", "Dec"}; Observable.fromArray(monthArray) .filter(item -> item.contains("y")) .filter(item -> item.contains("l")) .count() .subscribe(item -> System.out.println("we got: " + item + " from the Observable")); System.out.println("######################################################"); Observable.fromArray(monthArray) .filter(item -> item.contains("y")) .filter(item -> item.contains("l")) .subscribe(item -> System.out.println("we got: " + item + " item from the Observable"), Throwable::printStackTrace, () -> System.out.println("I am Done!! Completed normally")); } @Test void mul_Subject() { PublishSubject<Object> publishSubject = PublishSubject.create(); PublishSubject<Object> publishSubject1 = PublishSubject.create(); PublishSubject<Object> publishSubject2 = PublishSubject.create(); PublishSubject<Object> publishSubject3 = PublishSubject.create(); publishSubject.subscribe(x -> { log("一郎神: " + x); publishSubject1.onNext(x); }, throwable -> System.out.println("异常指向: 一郎神-> " + throwable.getMessage()), () -> System.out.println("Emission completed"), disposable -> System.out.println("onSubscribe") ); publishSubject1.subscribe(x -> { log("二郎神: " + x); publishSubject2.onNext(x); }, throwable -> publishSubject.onError(new RuntimeException("二郎神-> " + throwable.getMessage())), () -> System.out.println("Emission completed"), disposable -> System.out.println("onSubscribe") ); publishSubject2.subscribe(x -> { log("三郎神: " + x); publishSubject3.onNext(x); }, throwable -> publishSubject1.onError(new RuntimeException("三郎神-> " + throwable.getMessage())), () -> System.out.println("Emission completed"), disposable -> System.out.println("onSubscribe") ); publishSubject3.subscribe(x -> { log("四郎神: " + x); if ((Long) x == 2L) throw new RuntimeException("四郎神来耍下宝"); }, throwable -> publishSubject2.onError(new RuntimeException(throwable.getMessage())), () -> System.out.println("Emission completed"), disposable -> System.out.println("onSubscribe") ); publishSubject.onNext(1l); publishSubject.onNext(2l); } @Test void map_test() { String[] monthArray = {"Jan", "Feb", "Mar", "Apl", "Maly", "Jun", "July", "Aug", "Sept", "Oct", "Nov", "Dec"}; Observable.fromArray(monthArray) .map(String::toUpperCase) .subscribe(System.out::println); Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .filter(i -> i % 3 > 0) .map(i -> "#" + i * 10) .filter(s -> s.length() < 4) .subscribe(System.out::println); } @Test void flatmap_test() { Observable.range(1, 3).flatMap(item -> Observable.range(item, 3)).subscribe(value -> System.out.print(value + "->")); } @Test void flatmap_test2() { List<List<String>> lists = new ArrayList<>(); for (int i = 1; i < 4; i++) { List main_list = new ArrayList(); lists.add(main_list); for (int j = 1; j < 3; j++) { main_list.add(i + "—— 打虎 ——" + j); } } Observable.fromArray(lists.toArray()) .map(item -> ((List) item).toArray()) .flatMap(Observable::fromArray) .subscribe(System.out::println); System.out.println("++++++++++++++++++++++++++++++++++++++"); Observable.fromArray(lists.toArray()) .flatMap(item -> Observable.fromArray(((List) item).toArray())) .subscribe(System.out::println); System.out.println("++++++++++++++++++++++++++++++++++++++"); Observable.fromArray(lists.toArray()) .flatMapIterable(item -> (List) item) .subscribe(System.out::println); } Observable<Long> upload(int id) { return Observable.just(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L); } Observable<String> rate(Integer id) { return Observable.just("上传完毕!"); } @Test void flatMap3() { int id = new Random().nextInt(100); System.out.println(id); upload(id) .map(item -> { if ((id % 2) == 1) { return item; } else throw new RuntimeException("我就是个BUG!!"); }) .flatMap( bytes -> { //System.out.println(bytes); return Observable.empty(); }, e -> Observable.just(e.getMessage()), () -> rate(id) ) .subscribe(item -> System.out.println("we got: " + item.toString() + " from the Observable"), throwable -> System.out.println("异常-> " + throwable.getMessage()), () -> System.out.println("Emission completed")); } @Test void scan_test() { Integer[] prices = {100, 200, 300, 15, 15}; Observable.fromArray(prices).scan((item1, item2) -> item1 + item2).subscribe(integer -> System.out.println("amount: " + integer), Throwable::printStackTrace, () -> System.out.println("I am Done!! Completed normally")); } @Test void groupby_test() { String[] monthArray = {"January", "Feb", "March", "Apl", "May", "Jun", "July", "Aug", "Sept", "Oct", "Nov", "Dec"}; Observable.fromArray(monthArray).groupBy(item -> item.length() <= 3 ? "THREE" : item.length() < 6 ? ">4" : "DEFAULT").subscribe(observable -> { // if (Objects.equals(observable.getKey(), ">4")) observable.subscribe(item -> System.out.println("选中的分组所包含元素: " + item)); observable.subscribe(item -> log(item + ":" + observable.getKey())); System.out.println("*********************************************"); }); } @Test void groupby_test2() { String[] monthArray = {"January", "Feb", "March", "Apl", "May", "Jun", "July", "Aug", "Sept", "Oct", "Nov", "Dec"}; Observable.fromArray(monthArray).groupBy(item -> { //sleep(1,TimeUnit.SECONDS); return item.length() <= 3 ? "THREE" : item.length() < 6 ? ">4" : "DEFAULT"; }, String::toUpperCase).subscribe(observable -> { //if (Objects.equals(observable.getKey(), ">4")) observable.subscribe(item -> System.out.println("选中的分组所包含元素: " + item)); observable.subscribe(item -> { sleep(2, TimeUnit.SECONDS); log(item + ":" + observable.getKey()); }); System.out.println("*********************************************"); }); } @Test void merg_test() { Observable.merge(Observable.range(1, 5), Observable.range(10, 3)) .subscribe(item -> System.out.println("we got: " + item.toString() + " from the Observable"), throwable -> System.out.println("异常-> " + throwable.getMessage()), () -> System.out.println("Emission completed")); } @Test void zip_test() { final WeatherStation station = new BasicWeatherStation(); Observable<Temperature> temperature = station.temperature(); Observable<Wind> wind = station.wind(); Observable.zip(temperature, wind, Weather::new); //temperature.zipWith(wind, Weather::new); } @Test void zip_test2() { final WeatherStation station = new BasicWeatherStation(); Observable<Temperature> temperature = station.temperature(); Observable<Wind> wind = station.wind(); Observable<Weather> weatherObservable = Observable.zip(temperature, wind, Weather::new); //temperature.zipWith(wind, Weather::new); Observable<LocalDate> nextWeekDays = Observable.range(1, 7) .map(i -> LocalDate.now().plusDays(i)); Observable.fromArray(City.values()) .flatMap(city -> nextWeekDays.map(date -> new Vacation(city, date))) .flatMap(vacation -> Observable.zip( weatherObservable.filter(Weather::computeSunny), vacation.cheapFlightFrom(vacation.getWhere()), vacation.cheapHotel(), (w, f, h) -> { w.setSunny(true); return vacation.setWeather(w).setFlight(f).setHotel(h); } )) .subscribe(item -> System.out.println("we got: " + item.getWhere() + " 航班折扣:" + item.getFlight() .getDiscount() + "折 from the Observable"), throwable -> System.out.println("异常-> " + throwable.getMessage()), () -> System.out.println("Emission completed")); } @Test void zip_test3() { Integer[] numbers = {1, 2, 13, 34, 15, 17}; String[] fruits = {"苹果", "梨", "李子", "荔枝", "芒果"}; Observable<Integer> source1 = Observable.fromArray(numbers); Observable<String> source2 = Observable.fromArray(fruits); Observable<Integer> source3 = Observable.range(10, 3); Observable.zip(source1, source2, source3, (value1, value2, value3) -> value1 + ":" + value2 + "*" + value3) .subscribe(item -> System.out.println("we got: " + item + " from the Observable"), throwable -> System.out.println("异常-> " + throwable.getMessage()), () -> System.out.println("Emission completed")); } @Test void combineLatest_test() { Integer[] numbers = {1, 2, 13, 34, 15, 17}; String[] fruits = {"苹果", "梨", "李子", "荔枝", "芒果"}; Observable<Integer> source1 = Observable.fromArray(numbers); Observable<String> source2 = Observable.fromArray(fruits); Observable.combineLatest(source2, source1, (item1, item2) -> item1 + item2) .subscribe(item -> System.out.println("we got: " + item + " from the Observable"), throwable -> System.out.println("异常-> " + throwable.getMessage()), () -> System.out.println("Emission completed")); } @Test void combineLatest_test2() { Observable.combineLatest( interval(2, TimeUnit.SECONDS).map(x -> "Java" + x), interval(1, TimeUnit.SECONDS).map(x -> "Spring" + x), (s, f) -> f + ":" + s ).forEach(System.out::println); sleep(6, TimeUnit.SECONDS); } @Test void withLatestFrom_test() { Integer[] numbers = {1, 2, 13, 34, 15, 17}; String[] fruits = {"苹果", "梨", "李子", "荔枝", "芒果"}; // 此处加入delay通过对第一次发送元素的打的时间差来确定withLatestFrom带来的差异,以确定书中此处的论断 Observable<Integer> source1 = Observable.fromArray(numbers).delay(2, TimeUnit.MILLISECONDS); Observable<String> source2 = Observable.fromArray(fruits).delay(3, TimeUnit.MILLISECONDS); source1.withLatestFrom(source2, (item1, item2) -> item1 + item2) .forEach(System.out::println); System.out.println("#################################"); Observable<String> stringObservable1 = interval(2, TimeUnit.SECONDS).map(x -> "Java" + x); Observable<String> stringObservable2 = interval(1, TimeUnit.SECONDS).map(x -> "Spring" + x); stringObservable2.withLatestFrom(stringObservable1, (s, f) -> s + ":" + f) .forEach(System.out::println); sleep(6, TimeUnit.SECONDS); } @Test void amb_test() { Integer[] numbers = {1, 2, 13, 34, 15, 17}; String[] fruits = {"苹果", "梨", "李子", "荔枝", "芒果"}; Observable<Integer> source1 = Observable.fromArray(numbers).delay(1, TimeUnit.SECONDS); Observable<String> source2 = Observable.fromArray(fruits); Observable.ambArray(source1, source2) .forEach(System.out::println); } @Test void scan_test2() { Observable<BigInteger> scan2 = Observable .range(2, 10) .scan(BigInteger.ONE, (big, cur) -> big.multiply(BigInteger.valueOf(cur))); scan2.forEach(System.out::println); } /*public <R> Observable<R> reduce( R initialValue, BiFunction<R, ? super T, R> reducer) { return Observable.scan(initialValue, reducer).takeLast(1); }*/ @Test void reduce_test() { Observable .range(10, 20) .reduce(new ArrayList<>(), (list, item) -> { list.add(item); return list; }).subscribe(System.out::println); } @Test void reduce_test2() { Observable .range(10, 20) .reduce(BigInteger.ONE, (big, cur) -> big.multiply(BigInteger.valueOf(cur))).subscribe(System.out::println); } @Test void collect_test() { Observable .range(10, 20) .collect(ArrayList::new, List::add) .subscribe(System.out::println); } @Test void distinct_test() { Observable<LocalDate> dates = Observable.just( LocalDate.of(2018, 1, 3), LocalDate.of(2018, 3, 4), LocalDate.of(2018, 1, 5), LocalDate.of(2018, 11, 3) ); // get distinct months dates.map(LocalDate::getMonth) .distinct() .subscribe(System.out::println); System.out.println("############################"); // get distinct days dates.distinct(LocalDate::getMonth) .subscribe(System.out::println); } @Test void distinctUntilChanged_test() { Observable.just(1, 1, 1, 2, 2, 3, 3, 2, 1, 1) .distinctUntilChanged() .subscribe(i -> System.out.println("RECEIVED: " + i)); } @Test void distinctUntilChanged_test2() { Function<Integer, Integer> flags_mask = flags -> flags == 0 ? 0 : ~(flags | ((1 & flags) << 1) | ((2 & flags) >> 1)); Consumer<Integer> consumer= System.out::println; Observable.just("Apple", "Orange", "Appla", "Eatla", "HOHO", "Meta") .distinctUntilChanged(String::length) .subscribe(i -> System.out.println("RECEIVED: " + i)); Integer apply = flags_mask.apply(5); System.out.println(apply); consumer.accept(3); } @Test void take_skip_test() { Observable<Integer> range = Observable.range(1, 5); range.take(3) .collect(ArrayList::new, List::add) .subscribe(System.out::println); // [1, 2, 3] range.skip(3) .collect(ArrayList::new, List::add) .subscribe(System.out::println); // [4, 5] range.skip(5) .collect(ArrayList::new, List::add) .subscribe(System.out::println); // [] range.takeLast(2) .collect(ArrayList::new, List::add) .subscribe(System.out::println); // [4, 5] range.skipLast(2) .collect(ArrayList::new, List::add) .subscribe(System.out::println); // [1, 2, 3] range.takeUntil(x -> x == 3) .collect(ArrayList::new, List::add) .subscribe(System.out::println); // [1, 2, 3] range.takeWhile(x -> x != 3) .collect(ArrayList::new, List::add) .subscribe(System.out::println); // [1, 2] range.all(x -> x != 4) .subscribe(System.out::println); // [false] range.contains(4) .subscribe(System.out::println); // [true] } @Test void compose_test() { Observable.just("Apple", "Orange", "Appla", "Eatla", "HOHO","Meta") .collect(ImmutableList::builder, ImmutableList.Builder::add) .map(ImmutableList.Builder::build) .subscribe(System.out::println); Observable.range(1,15) .collect(ImmutableList::builder, ImmutableList.Builder::add) .map(ImmutableList.Builder::build) .subscribe(System.out::println); } @Test void compose_test2() { Observable.just("Apple", "Orange", "Appla", "Eatla", "HOHO","Meta") .compose(toImmutableList()) .subscribe(System.out::println); Observable.range(1,15) .compose(toImmutableList()) .subscribe(System.out::println); } public static <T> ObservableTransformer<T,ImmutableList<T>> toImmutableList(){ return upstream -> upstream.collect(ImmutableList::<T>builder, ImmutableList.Builder::add) .map(ImmutableList.Builder::build) .toObservable(); //must turn Single into Observable } @Test void lift_test() { Observable.range(1,5) .lift(doOnEmpty(() -> System.out.println("Operation 1 Empty!"))) .subscribe(v -> System.out.println("Operation 1: " + v)); Observable.<Integer>empty() .lift(doOnEmpty(() -> System.out.println("Operation 2 Empty!"))) .subscribe(v -> System.out.println("Operation 2: " + v)); } public static <T> ObservableOperator<T,T> doOnEmpty(Action action){ return observer -> new DisposableObserver<T>() { boolean isEmpty = true; @Override public void onNext(T value) { isEmpty = false; observer.onNext(value); } @Override public void onError(Throwable t) { observer.onError(t); } @Override public void onComplete() { if (isEmpty) { try { action.run(); } catch (Exception e) { onError(e); return; } } observer.onComplete(); } }; } }