All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.reactivex.interop.RxJava3Interop Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2016-present, RxJava Contributors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.reactivex.interop;

import java.util.*;
import java.util.concurrent.Callable;

import org.reactivestreams.Publisher;

import io.reactivex.common.*;
import io.reactivex.common.Scheduler.Worker;
import io.reactivex.common.annotations.*;
import io.reactivex.common.functions.*;
import io.reactivex.common.internal.functions.*;
import io.reactivex.common.internal.utils.*;
import io.reactivex.flowable.*;
import io.reactivex.flowable.internal.operators.*;
import io.reactivex.interop.internal.operators.*;
import io.reactivex.observable.*;
import io.reactivex.observable.Observable;

/**
 * The base utility class that hosts factory methods and
 * functions to be used with the
 * various base classes' {@code to(Function)} methods to
 * enable interoperation between the base reactive types
 * and some of their features.
 * @since 3.0.0
 */
public final class RxJava3Interop {

    private RxJava3Interop() {
        throw new IllegalStateException("No instances!");
    }

    // --------------------------------------------------------------------------------------------------
    // Base type conversions
    // --------------------------------------------------------------------------------------------------

    public static  Flowable toFlowable(ObservableSource source, BackpressureStrategy strategy) {
        ObjectHelper.requireNonNull(source, "source is null");
        Flowable flowable = new FlowableFromObservable(source);
        switch (strategy) {
        case BUFFER:
            flowable = flowable.onBackpressureBuffer();
            break;
        case DROP:
            flowable = flowable.onBackpressureDrop();
            break;
        case ERROR:
            flowable = new FlowableOnBackpressureError(flowable);
            break;
        case LATEST:
            flowable = flowable.onBackpressureLatest();
            break;
        default:
        }
        return flowable;
    }

    public static  Flowable toFlowable(SingleSource source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaFlowablePlugins.onAssembly(new SingleToFlowable(source));
    }

    public static  Flowable toFlowable(MaybeSource source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaFlowablePlugins.onAssembly(new MaybeToFlowable(source));
    }

    public static  Flowable toFlowable(CompletableSource source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaFlowablePlugins.onAssembly(new CompletableToFlowable(source));
    }

    public static  Observable toObservable(Flowable source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaObservablePlugins.onAssembly(new ObservableFromPublisher(source));
    }

    // --------------------------------------------------------------------------------------------------
    // Flowable operators that return a different basetype
    // --------------------------------------------------------------------------------------------------

    public static  Single> toList(Flowable source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableToListSingle>(source));
    }

    public static  Single> toList(Flowable source, int capacityHint) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.verifyPositive(capacityHint, "capacityHint");
        return RxJavaObservablePlugins.onAssembly(new FlowableToListSingle>(source, Functions.createArrayList(capacityHint)));
    }

    public static > Single toList(Flowable source, Callable collectionSupplier) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(collectionSupplier, "collectionSupplier is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableToListSingle(source, collectionSupplier));
    }

    public static  Completable ignoreElements(Flowable source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableIgnoreElementsCompletable(source));
    }

    public static  Maybe reduce(Flowable source, BiFunction reducer) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(reducer, "reducer is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableReduceMaybe(source, reducer));
    }

    public static  Single reduceWith(Flowable source, Callable seed, BiFunction reducer) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(seed, "seed is null");
        ObjectHelper.requireNonNull(reducer, "reducer is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableReduceWithSingle(source, seed, reducer));
    }

    public static  Single reduce(Flowable source, R seed, BiFunction reducer) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(seed, "seed is null");
        ObjectHelper.requireNonNull(reducer, "reducer is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableReduceSeedSingle(source, seed, reducer));
    }

    public static  Flowable flatMapSingle(Flowable source, Function> mapper) {
        return flatMapSingle(source, mapper, false, Flowable.bufferSize());
    }

    public static  Flowable flatMapSingle(Flowable source,
            Function> mapper, boolean delayError, int maxConcurrency) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
        return RxJavaFlowablePlugins.onAssembly(new FlowableFlatMapSingle(source, mapper, delayError, maxConcurrency));
    }

    public static  Flowable flatMapMaybe(Flowable source,
            Function> mapper) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return flatMapMaybe(source, mapper, false, Flowable.bufferSize());
    }

    public static  Flowable flatMapMaybe(Flowable source,
            Function> mapper, boolean delayError, int maxConcurrency) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
        return RxJavaFlowablePlugins.onAssembly(new FlowableFlatMapMaybe(source, mapper, delayError, maxConcurrency));
    }

    public static  Completable flatMapCompletable(Flowable source,
            Function mapper) {
        return flatMapCompletable(source, mapper, false, Flowable.bufferSize());
    }

    public static  Completable flatMapCompletable(Flowable source,
            Function mapper, boolean delayError, int prefetch) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        ObjectHelper.verifyPositive(prefetch, "prefetch");
        return RxJavaObservablePlugins.onAssembly(new FlowableFlatMapCompletableCompletable(source, mapper, delayError, prefetch));
    }

    public static  Flowable flatMapPublisher(Single source, Function> mapper) {
        return toFlowable(source).flatMap(mapper);
    }

    public static  Flowable flatMapPublisher(Maybe source, Function> mapper) {
        return toFlowable(source).flatMap(mapper);
    }

    public static  Flowable flattenAsFlowable(Single source,
            Function> mapper) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return RxJavaFlowablePlugins.onAssembly(new SingleFlatMapIterableFlowable(source, mapper));
    }

    public static  Flowable flattenAsFlowable(Maybe source,
            Function> mapper) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return RxJavaFlowablePlugins.onAssembly(new MaybeFlatMapIterableFlowable(source, mapper));
    }

    public static  Completable concatCompletable(Flowable sources) {
        ObjectHelper.requireNonNull(sources, "sources is null");
        return concatCompletable(sources, 2);
    }

    public static  Completable concatCompletable(Flowable sources, int prefetch) {
        ObjectHelper.requireNonNull(sources, "sources is null");
        ObjectHelper.verifyPositive(prefetch, "prefetch");
        return RxJavaObservablePlugins.onAssembly(new CompletableConcat(sources, prefetch));
    }

    public static  Completable mergeCompletable(Flowable sources) {
        return mergeCompletable(sources, Integer.MAX_VALUE);
    }

    public static  Completable mergeCompletable(Flowable sources, int maxConcurrency) {
        ObjectHelper.requireNonNull(sources, "sources is null");
        ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
        return RxJavaObservablePlugins.onAssembly(new CompletableMerge(sources, maxConcurrency, false));
    }

    public static  Completable mergeCompletableDelayError(Flowable sources) {
        return mergeCompletableDelayError(sources, Integer.MAX_VALUE);
    }

    public static  Completable mergeCompletableDelayError(Flowable sources, int maxConcurrency) {
        ObjectHelper.requireNonNull(sources, "sources is null");
        ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
        return RxJavaObservablePlugins.onAssembly(new CompletableMerge(sources, maxConcurrency, true));
    }

    public static  Flowable concatSingle(Flowable> sources) {
        return concatSingle(sources, 2);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static  Flowable concatSingle(Flowable> sources, int prefetch) {
        ObjectHelper.requireNonNull(sources, "sources is null");
        ObjectHelper.verifyPositive(prefetch, "prefetch");
        return RxJavaFlowablePlugins.onAssembly(new FlowableConcatMapPublisher(sources, InteropInternalHelper.toFlowable(), prefetch, ErrorMode.IMMEDIATE));
    }

    public static  Flowable concatMaybe(Flowable> sources) {
        return concatMaybe(sources, 2);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static  Flowable concatMaybe(Flowable> sources, int prefetch) {
        ObjectHelper.requireNonNull(sources, "sources is null");
        ObjectHelper.verifyPositive(prefetch, "prefetch");
        return RxJavaFlowablePlugins.onAssembly(new FlowableConcatMapPublisher(sources, MaybeToPublisher.instance(), prefetch, ErrorMode.IMMEDIATE));
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static  Flowable mergeSingle(Flowable> sources) {
        ObjectHelper.requireNonNull(sources, "sources is null");
        return RxJavaFlowablePlugins.onAssembly(new FlowableFlatMapPublisher(sources, InteropInternalHelper.toFlowable(), false, Integer.MAX_VALUE, Flowable.bufferSize()));
    }

    public static  Flowable mergeMaybe(Flowable> sources) {
        return mergeMaybe(sources, Integer.MAX_VALUE);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static  Flowable mergeMaybe(Flowable> sources, int maxConcurrency) {
        ObjectHelper.requireNonNull(sources, "source is null");
        ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
        return RxJavaFlowablePlugins.onAssembly(new FlowableFlatMapPublisher(sources, MaybeToPublisher.instance(), false, maxConcurrency, Flowable.bufferSize()));
    }

    public static  Single first(Flowable source, T defaultItem) {
        return elementAt(source, 0, defaultItem);
    }

    public static  Single firstOrError(Flowable source) {
        return elementAtOrError(source, 0);
    }

    public static  Maybe firstElement(Flowable source) {
        return elementAt(source, 0);
    }

    public static  Single last(Flowable source, T defaultItem) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(defaultItem, "defaultItem is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableLastSingle(source, defaultItem));
    }

    public static  Single lastOrError(Flowable source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableLastSingle(source, null));
    }

    public static  Maybe lastElement(Flowable source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableLastMaybe(source));
    }

    public static  Single single(Flowable source, T defaultItem) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(defaultItem, "defaultItem is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableSingleSingle(source, defaultItem));
    }

    public static  Single singleOrError(Flowable source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableSingleSingle(source, null));
    }

    public static  Maybe singleElement(Flowable source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableSingleMaybe(source));
    }

    public static  Maybe elementAt(Flowable source, long index) {
        ObjectHelper.requireNonNull(source, "source is null");
        if (index < 0L) {
            throw new IndexOutOfBoundsException("index >= 0 required but it was " + index);
        }
        return RxJavaObservablePlugins.onAssembly(new FlowableElementAtMaybe(source, index));
    }

    public static  Single elementAt(Flowable source, long index, T defaultItem) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(defaultItem, "defaultItem is null");
        if (index < 0L) {
            throw new IndexOutOfBoundsException("index >= 0 required but it was " + index);
        }
        return RxJavaObservablePlugins.onAssembly(new FlowableElementAtSingle(source, index, defaultItem));
    }

    public static  Single elementAtOrError(Flowable source, long index) {
        ObjectHelper.requireNonNull(source, "source is null");
        if (index < 0) {
            throw new IndexOutOfBoundsException("index >= 0 required but it was " + index);
        }
        return RxJavaObservablePlugins.onAssembly(new FlowableElementAtSingle(source, index, null));
    }

    public static  Single collect(Flowable source, Callable collectionSupplier, BiConsumer collector) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(collectionSupplier, "collectionSupplier is null");
        ObjectHelper.requireNonNull(collector, "collector is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableCollectSingle(source, collectionSupplier, collector));
    }

    public static  Single any(Flowable source, Predicate predicate) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(predicate, "predicate is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableAnySingle(source, predicate));
    }

    public static  Single all(Flowable source, Predicate predicate) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(predicate, "predicate is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableAllSingle(source, predicate));
    }

    public static  Single isEmpty(Flowable source) {
        return all(source, Functions.alwaysFalse());
    }

    public static  Single count(Flowable source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaObservablePlugins.onAssembly(new FlowableCountSingle(source));
    }

    /**
     * Returns a Single that emits a single HashMap containing all items emitted by the source Publisher,
     * mapped by the keys returned by a specified {@code keySelector} function.
     * 

* *

* If more than one source item maps to the same key, the HashMap will contain the latest of those items. *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toMap} does not operate by default on a particular {@link Scheduler}.
*
* * @param the key type of the Map * @param the source value type * @param source the source Flowable instance * @param keySelector * the function that extracts the key from a source item to be used in the HashMap * @return a Single that emits a single item: a HashMap containing the mapped items from the source * Publisher * @see ReactiveX operators documentation: To */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single> toMap(Flowable source, final Function keySelector) { ObjectHelper.requireNonNull(keySelector, "keySelector is null"); return collect(source, HashMapSupplier.asCallable(), Functions.toMapKeySelector(keySelector)); } /** * Returns a Single that emits a single HashMap containing values corresponding to items emitted by the * source Publisher, mapped by the keys returned by a specified {@code keySelector} function. *

* *

* If more than one source item maps to the same key, the HashMap will contain a single entry that * corresponds to the latest of those items. *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toMap} does not operate by default on a particular {@link Scheduler}.
*
* * @param the key type of the Map * @param the value type of the Map * @param the source value type * @param source the source Flowable instance * @param keySelector * the function that extracts the key from a source item to be used in the HashMap * @param valueSelector * the function that extracts the value from a source item to be used in the HashMap * @return a Single that emits a single item: a HashMap containing the mapped items from the source * Publisher * @see ReactiveX operators documentation: To */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single> toMap(Flowable source, final Function keySelector, final Function valueSelector) { ObjectHelper.requireNonNull(keySelector, "keySelector is null"); ObjectHelper.requireNonNull(valueSelector, "valueSelector is null"); return collect(source, HashMapSupplier.asCallable(), Functions.toMapKeyValueSelector(keySelector, valueSelector)); } /** * Returns a Single that emits a single Map, returned by a specified {@code mapFactory} function, that * contains keys and values extracted from the items emitted by the source Publisher. *

* *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toMap} does not operate by default on a particular {@link Scheduler}.
*
* * @param the key type of the Map * @param the value type of the Map * @param the source value type * @param source the source Flowable instance * @param keySelector * the function that extracts the key from a source item to be used in the Map * @param valueSelector * the function that extracts the value from the source items to be used as value in the Map * @param mapSupplier * the function that returns a Map instance to be used * @return a Flowable that emits a single item: a Map that contains the mapped items emitted by the * source Publisher * @see ReactiveX operators documentation: To */ @SuppressWarnings("unchecked") @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single> toMap(Flowable source, final Function keySelector, final Function valueSelector, final Callable> mapSupplier) { ObjectHelper.requireNonNull(keySelector, "keySelector is null"); ObjectHelper.requireNonNull(valueSelector, "valueSelector is null"); return (Single>)collect(source, mapSupplier, Functions.toMapKeyValueSelector(keySelector, valueSelector)); } /** * Returns a Single that emits a single HashMap that contains an ArrayList of items emitted by the * source Publisher keyed by a specified {@code keySelector} function. *

* *

*
Backpressure:
*
This operator does not support backpressure as by intent it is requesting and buffering everything.
*
Scheduler:
*
{@code toMultimap} does not operate by default on a particular {@link Scheduler}.
*
* * @param the key type of the Map * @param the source value type * @param source the source Flowable instance * @param keySelector * the function that extracts the key from the source items to be used as key in the HashMap * @return a Single that emits a single item: a HashMap that contains an ArrayList of items mapped from * the source Publisher * @see ReactiveX operators documentation: To */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single>> toMultimap(Flowable source, Function keySelector) { Function valueSelector = Functions.identity(); Callable>> mapSupplier = HashMapSupplier.asCallable(); Function> collectionFactory = ArrayListSupplier.asFunction(); return toMultimap(source, keySelector, valueSelector, mapSupplier, collectionFactory); } /** * Returns a Single that emits a single HashMap that contains an ArrayList of values extracted by a * specified {@code valueSelector} function from items emitted by the source Publisher, keyed by a * specified {@code keySelector} function. *

* *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toMultimap} does not operate by default on a particular {@link Scheduler}.
*
* * @param the key type of the Map * @param the value type of the Map * @param the source value type * @param source the source Flowable instance * @param keySelector * the function that extracts a key from the source items to be used as key in the HashMap * @param valueSelector * the function that extracts a value from the source items to be used as value in the HashMap * @return a Single that emits a single item: a HashMap that contains an ArrayList of items mapped from * the source Publisher * @see ReactiveX operators documentation: To */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single>> toMultimap(Flowable source, Function keySelector, Function valueSelector) { Callable>> mapSupplier = HashMapSupplier.asCallable(); Function> collectionFactory = ArrayListSupplier.asFunction(); return toMultimap(source, keySelector, valueSelector, mapSupplier, collectionFactory); } /** * Returns a Single that emits a single Map, returned by a specified {@code mapFactory} function, that * contains a custom collection of values, extracted by a specified {@code valueSelector} function from * items emitted by the source Publisher, and keyed by the {@code keySelector} function. *

* *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toMultimap} does not operate by default on a particular {@link Scheduler}.
*
* * @param the key type of the Map * @param the value type of the Map * @param the source value type * @param source the source Flowable instance * @param keySelector * the function that extracts a key from the source items to be used as the key in the Map * @param valueSelector * the function that extracts a value from the source items to be used as the value in the Map * @param mapSupplier * the function that returns a Map instance to be used * @param collectionFactory * the function that returns a Collection instance for a particular key to be used in the Map * @return a Single that emits a single item: a Map that contains the collection of mapped items from * the source Publisher * @see ReactiveX operators documentation: To */ @SuppressWarnings("unchecked") @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single>> toMultimap( Flowable source, final Function keySelector, final Function valueSelector, final Callable>> mapSupplier, final Function> collectionFactory) { ObjectHelper.requireNonNull(keySelector, "keySelector is null"); ObjectHelper.requireNonNull(valueSelector, "valueSelector is null"); ObjectHelper.requireNonNull(mapSupplier, "mapSupplier is null"); ObjectHelper.requireNonNull(collectionFactory, "collectionFactory is null"); return (Single>>)collect(source, mapSupplier, Functions.toMultimapKeyValueSelector(keySelector, valueSelector, collectionFactory)); } /** * Returns a Single that emits a single Map, returned by a specified {@code mapFactory} function, that * contains an ArrayList of values, extracted by a specified {@code valueSelector} function from items * emitted by the source Publisher and keyed by the {@code keySelector} function. *

* *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toMultimap} does not operate by default on a particular {@link Scheduler}.
*
* * @param the key type of the Map * @param the value type of the Map * @param the source value type * @param source the source Flowable instance * @param keySelector * the function that extracts a key from the source items to be used as the key in the Map * @param valueSelector * the function that extracts a value from the source items to be used as the value in the Map * @param mapSupplier * the function that returns a Map instance to be used * @return a Single that emits a single item: a Map that contains a list items mapped from the source * Publisher * @see ReactiveX operators documentation: To */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single>> toMultimap( Flowable source, Function keySelector, Function valueSelector, Callable>> mapSupplier ) { return toMultimap(source, keySelector, valueSelector, mapSupplier, ArrayListSupplier.asFunction()); } /** * Returns a Single that emits a list that contains the items emitted by the source Publisher, in a * sorted order. Each item emitted by the Publisher must implement {@link Comparable} with respect to all * other items in the sequence. * *

If any item emitted by this Flowable does not implement {@link Comparable} with respect to * all other items emitted by this Flowable, no items will be emitted and the * sequence is terminated with a {@link ClassCastException}. *

* *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toSortedList} does not operate by default on a particular {@link Scheduler}.
*
* @param the source value type * @param source the source Flowable instance * @return a Single that emits a list that contains the items emitted by the source Publisher in * sorted order * @see ReactiveX operators documentation: To */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single> toSortedList(Flowable source) { return toSortedList(source, Functions.naturalComparator()); } /** * Returns a Single that emits a list that contains the items emitted by the source Publisher, in a * sorted order based on a specified comparison function. *

* *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toSortedList} does not operate by default on a particular {@link Scheduler}.
*
* * @param the source value type * @param source the source Flowable instance * @param comparator * a function that compares two items emitted by the source Publisher and returns an Integer * that indicates their sort order * @return a Single that emits a list that contains the items emitted by the source Publisher in * sorted order * @see ReactiveX operators documentation: To */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single> toSortedList(Flowable source, final Comparator comparator) { ObjectHelper.requireNonNull(comparator, "comparator is null"); return toList(source).map(Functions.listSorter(comparator)); } /** * Returns a Single that emits a list that contains the items emitted by the source Publisher, in a * sorted order based on a specified comparison function. *

* *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toSortedList} does not operate by default on a particular {@link Scheduler}.
*
* * @param the source value type * @param source the source Flowable instance * @param comparator * a function that compares two items emitted by the source Publisher and returns an Integer * that indicates their sort order * @param capacityHint * the initial capacity of the ArrayList used to accumulate items before sorting * @return a Single that emits a list that contains the items emitted by the source Publisher in * sorted order * @see ReactiveX operators documentation: To * @since 2.0 */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single> toSortedList(Flowable source, final Comparator comparator, int capacityHint) { ObjectHelper.requireNonNull(comparator, "comparator is null"); return toList(source, capacityHint).map(Functions.listSorter(comparator)); } /** * Returns a Flowable that emits a list that contains the items emitted by the source Publisher, in a * sorted order. Each item emitted by the Publisher must implement {@link Comparable} with respect to all * other items in the sequence. * *

If any item emitted by this Flowable does not implement {@link Comparable} with respect to * all other items emitted by this Flowable, no items will be emitted and the * sequence is terminated with a {@link ClassCastException}. *

* *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the source {@code Publisher} in an * unbounded manner (i.e., without applying backpressure to it).
*
Scheduler:
*
{@code toSortedList} does not operate by default on a particular {@link Scheduler}.
*
* * @param the source value type * @param source the source Flowable instance * @param capacityHint * the initial capacity of the ArrayList used to accumulate items before sorting * @return a Flowable that emits a list that contains the items emitted by the source Publisher in * sorted order * @see ReactiveX operators documentation: To * @since 2.0 */ @CheckReturnValue @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) @SchedulerSupport(SchedulerSupport.NONE) public static Single> toSortedList(Flowable source, int capacityHint) { return toSortedList(source, Functions.naturalComparator(), capacityHint); } /** * Allows the use of operators for controlling the timing around when * actions scheduled on workers are actually done. This makes it possible to * layer additional behavior on this {@link Scheduler}. The only parameter * is a function that flattens an {@link Flowable} of {@link Flowable} * of {@link Completable}s into just one {@link Completable}. There must be * a chain of operators connecting the returned value to the source * {@link Flowable} otherwise any work scheduled on the returned * {@link Scheduler} will not be executed. *

* When {@link Scheduler#createWorker()} is invoked a {@link Flowable} of * {@link Completable}s is onNext'd to the combinator to be flattened. If * the inner {@link Flowable} is not immediately subscribed to an calls to * {@link Worker#schedule} are buffered. Once the {@link Flowable} is * subscribed to actions are then onNext'd as {@link Completable}s. *

* Finally the actions scheduled on the parent {@link Scheduler} when the * inner most {@link Completable}s are subscribed to. *

* When the {@link Worker} is unsubscribed the {@link Completable} emits an * onComplete and triggers any behavior in the flattening operator. The * {@link Flowable} and all {@link Completable}s give to the flattening * function never onError. *

* Limit the amount concurrency two at a time without creating a new fix * size thread pool: * *

     * Scheduler limitScheduler = Schedulers.computation().when(workers -> {
     *  // use merge max concurrent to limit the number of concurrent
     *  // callbacks two at a time
     *  return Completable.merge(Flowable.merge(workers), 2);
     * });
     * 
*

* This is a slightly different way to limit the concurrency but it has some * interesting benefits and drawbacks to the method above. It works by * limited the number of concurrent {@link Worker}s rather than individual * actions. Generally each {@link Flowable} uses its own {@link Worker}. * This means that this will essentially limit the number of concurrent * subscribes. The danger comes from using operators like * {@link Flowable#zip(org.reactivestreams.Publisher, org.reactivestreams.Publisher, io.reactivex.common.functions.BiFunction)} where * subscribing to the first {@link Flowable} could deadlock the * subscription to the second. * *

     * Scheduler limitScheduler = Schedulers.computation().when(workers -> {
     *  // use merge max concurrent to limit the number of concurrent
     *  // Flowables two at a time
     *  return Completable.merge(Flowable.merge(workers, 2));
     * });
     * 
* * Slowing down the rate to no more than than 1 a second. This suffers from * the same problem as the one above I could find an {@link Flowable} * operator that limits the rate without dropping the values (aka leaky * bucket algorithm). * *
     * Scheduler slowScheduler = Schedulers.computation().when(workers -> {
     *  // use concatenate to make each worker happen one at a time.
     *  return Completable.concat(workers.map(actions -> {
     *      // delay the starting of the next worker by 1 second.
     *      return Completable.merge(actions.delaySubscription(1, TimeUnit.SECONDS));
     *  }));
     * });
     * 
* * @param a Scheduler and a Subscription * @param scheduler the target scheduler to wrap * @param combine the function that takes a two-level nested Flowable sequence of a Completable and returns * the Completable that will be subscribed to and should trigger the execution of the scheduled Actions. * @return the Scheduler with the customized execution behavior */ @SuppressWarnings("unchecked") @Experimental @NonNull public static S when(Scheduler scheduler, @NonNull Function>, Completable> combine) { ObjectHelper.requireNonNull(scheduler, "scheduler is null"); ObjectHelper.requireNonNull(combine, "combine is null"); return (S) new SchedulerWhen(combine, scheduler); } public static Single takeUntil(Single source, Publisher other) { ObjectHelper.requireNonNull(source, "source is null"); ObjectHelper.requireNonNull(other, "other is null"); return RxJavaObservablePlugins.onAssembly(new SingleTakeUntilPublisher(source, other)); } public static Maybe takeUntil(Maybe source, Publisher other) { ObjectHelper.requireNonNull(source, "source is null"); ObjectHelper.requireNonNull(other, "other is null"); return RxJavaObservablePlugins.onAssembly(new MaybeTakeUntilPublisher(source, other)); } public static Maybe timeout(Maybe source, Publisher other) { ObjectHelper.requireNonNull(source, "source is null"); ObjectHelper.requireNonNull(other, "other is null"); return RxJavaObservablePlugins.onAssembly(new MaybeTimeoutPublisher(source, other, null)); } public static Maybe timeout(Maybe source, Publisher other, Maybe fallback) { ObjectHelper.requireNonNull(source, "source is null"); ObjectHelper.requireNonNull(other, "other is null"); ObjectHelper.requireNonNull(fallback, "fallback is null"); return RxJavaObservablePlugins.onAssembly(new MaybeTimeoutPublisher(source, other, fallback)); } }