diff --git a/src/main/java/io/reactivex/Flowable.java b/src/main/java/io/reactivex/Flowable.java index 4e9c2d2ee0..f87cde880c 100644 --- a/src/main/java/io/reactivex/Flowable.java +++ b/src/main/java/io/reactivex/Flowable.java @@ -7669,9 +7669,24 @@ public final Flowable dematerialize() { } /** - * Returns a Flowable that emits all items emitted by the source Publisher that are distinct. + * Returns a Flowable that emits all items emitted by the source Publisher that are distinct + * based on {@link Object#equals(Object)} comparison. *

* + *

+ * It is recommended the elements' class {@code T} in the flow overrides the default {@code Object.equals()} and {@link Object#hashCode()} to provide + * meaningful comparison between items as the default Java implementation only considers reference equivalence. + *

+ * By default, {@code distinct()} uses an internal {@link java.util.HashSet} per Subscriber to remember + * previously seen items and uses {@link java.util.Set#add(Object)} returning {@code false} as the + * indicator for duplicates. + *

+ * Note that this internal {@code HashSet} may grow unbounded as items won't be removed from it by + * the operator. Therefore, using very long or infinite upstream (with very distinct elements) may lead + * to {@code OutOfMemoryError}. + *

+ * Customizing the retention policy can happen only by providing a custom {@link java.util.Collection} implementation + * to the {@link #distinct(Function, Callable)} overload. *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the source {@code Publisher}'s @@ -7683,6 +7698,8 @@ public final Flowable dematerialize() { * @return a Flowable that emits only those items emitted by the source Publisher that are distinct from * each other * @see ReactiveX operators documentation: Distinct + * @see #distinct(Function) + * @see #distinct(Function, Callable) */ @SuppressWarnings({ "rawtypes", "unchecked" }) @CheckReturnValue @@ -7694,9 +7711,24 @@ public final Flowable distinct() { /** * Returns a Flowable that emits all items emitted by the source Publisher that are distinct according - * to a key selector function. + * to a key selector function and based on {@link Object#equals(Object)} comparison of the objects + * returned by the key selector function. *

* + *

+ * It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} and {@link Object#hashCode()} to provide + * meaningful comparison between the key objects as the default Java implementation only considers reference equivalence. + *

+ * By default, {@code distinct()} uses an internal {@link java.util.HashSet} per Subscriber to remember + * previously seen keys and uses {@link java.util.Set#add(Object)} returning {@code false} as the + * indicator for duplicates. + *

+ * Note that this internal {@code HashSet} may grow unbounded as keys won't be removed from it by + * the operator. Therefore, using very long or infinite upstream (with very distinct keys) may lead + * to {@code OutOfMemoryError}. + *

+ * Customizing the retention policy can happen only by providing a custom {@link java.util.Collection} implementation + * to the {@link #distinct(Function, Callable)} overload. *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the source {@code Publisher}'s @@ -7711,6 +7743,7 @@ public final Flowable distinct() { * is distinct from another one or not * @return a Flowable that emits those items emitted by the source Publisher that have distinct keys * @see ReactiveX operators documentation: Distinct + * @see #distinct(Function, Callable) */ @CheckReturnValue @BackpressureSupport(BackpressureKind.FULL) @@ -7721,9 +7754,13 @@ public final Flowable distinct(Function keySelector) { /** * Returns a Flowable that emits all items emitted by the source Publisher that are distinct according - * to a key selector function. + * to a key selector function and based on {@link Object#equals(Object)} comparison of the objects + * returned by the key selector function. *

* + *

+ * It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} and {@link Object#hashCode()} to provide + * meaningful comparison between the key objects as the default Java implementation only considers reference equivalence. *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the source {@code Publisher}'s @@ -7754,9 +7791,18 @@ public final Flowable distinct(Function keySelector, /** * Returns a Flowable that emits all items emitted by the source Publisher that are distinct from their - * immediate predecessors. + * immediate predecessors based on {@link Object#equals(Object)} comparison. *

* + *

+ * It is recommended the elements' class {@code T} in the flow overrides the default {@code Object.equals()} to provide + * meaningful comparison between items as the default Java implementation only considers reference equivalence. + * Alternatively, use the {@link #distinctUntilChanged(BiPredicate)} overload and provide a comparison function + * in case the class {@code T} can't be overridden with custom {@code equals()} or the comparison itself + * should happen on different terms or properties of the class {@code T}. + *

+ * Note that the operator always retains the latest item from upstream regardless of the comparison result + * and uses it in the next comparison with the next upstream item. *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the source {@code Publisher}'s @@ -7768,6 +7814,7 @@ public final Flowable distinct(Function keySelector, * @return a Flowable that emits those items from the source Publisher that are distinct from their * immediate predecessors * @see ReactiveX operators documentation: Distinct + * @see #distinctUntilChanged(BiPredicate) */ @CheckReturnValue @BackpressureSupport(BackpressureKind.FULL) @@ -7778,9 +7825,20 @@ public final Flowable distinctUntilChanged() { /** * Returns a Flowable that emits all items emitted by the source Publisher that are distinct from their - * immediate predecessors, according to a key selector function. + * immediate predecessors, according to a key selector function and based on {@link Object#equals(Object)} comparison + * of those objects returned by the key selector function. *

* + *

+ * It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} to provide + * meaningful comparison between the key objects as the default Java implementation only considers reference equivalence. + * Alternatively, use the {@link #distinctUntilChanged(BiPredicate)} overload and provide a comparison function + * in case the class {@code K} can't be overridden with custom {@code equals()} or the comparison itself + * should happen on different terms or properties of the item class {@code T} (for which the keys can be + * derived via a similar selector). + *

+ * Note that the operator always retains the latest key from upstream regardless of the comparison result + * and uses it in the next comparison with the next key derived from the next upstream item. *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the source {@code Publisher}'s @@ -7810,6 +7868,9 @@ public final Flowable distinctUntilChanged(Function keySele * immediate predecessors when compared with each other via the provided comparator function. *

* + *

+ * Note that the operator always retains the latest item from upstream regardless of the comparison result + * and uses it in the next comparison with the next upstream item. *

*
Backpressure:
*
The operator doesn't interfere with backpressure which is determined by the source {@code Publisher}'s diff --git a/src/main/java/io/reactivex/Observable.java b/src/main/java/io/reactivex/Observable.java index e15da78bfd..be140a5a11 100644 --- a/src/main/java/io/reactivex/Observable.java +++ b/src/main/java/io/reactivex/Observable.java @@ -7011,9 +7011,25 @@ public final Observable dematerialize() { } /** - * Returns an Observable that emits all items emitted by the source ObservableSource that are distinct. + * Returns an Observable that emits all items emitted by the source ObservableSource that are distinct + * based on {@link Object#equals(Object)} comparison. *

* + *

+ * It is recommended the elements' class {@code T} in the flow overrides the default {@code Object.equals()} + * and {@link Object#hashCode()} to provide meaningful comparison between items as the default Java + * implementation only considers reference equivalence. + *

+ * By default, {@code distinct()} uses an internal {@link java.util.HashSet} per Observer to remember + * previously seen items and uses {@link java.util.Set#add(Object)} returning {@code false} as the + * indicator for duplicates. + *

+ * Note that this internal {@code HashSet} may grow unbounded as items won't be removed from it by + * the operator. Therefore, using very long or infinite upstream (with very distinct elements) may lead + * to {@code OutOfMemoryError}. + *

+ * Customizing the retention policy can happen only by providing a custom {@link java.util.Collection} implementation + * to the {@link #distinct(Function, Callable)} overload. *

*
Scheduler:
*
{@code distinct} does not operate by default on a particular {@link Scheduler}.
@@ -7022,6 +7038,8 @@ public final Observable dematerialize() { * @return an Observable that emits only those items emitted by the source ObservableSource that are distinct from * each other * @see ReactiveX operators documentation: Distinct + * @see #distinct(Function) + * @see #distinct(Function, Callable) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -7031,9 +7049,25 @@ public final Observable distinct() { /** * Returns an Observable that emits all items emitted by the source ObservableSource that are distinct according - * to a key selector function. + * to a key selector function and based on {@link Object#equals(Object)} comparison of the objects + * returned by the key selector function. *

* + *

+ * It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} + * and {@link Object#hashCode()} to provide meaningful comparison between the key objects as the default + * Java implementation only considers reference equivalence. + *

+ * By default, {@code distinct()} uses an internal {@link java.util.HashSet} per Observer to remember + * previously seen keys and uses {@link java.util.Set#add(Object)} returning {@code false} as the + * indicator for duplicates. + *

+ * Note that this internal {@code HashSet} may grow unbounded as keys won't be removed from it by + * the operator. Therefore, using very long or infinite upstream (with very distinct keys) may lead + * to {@code OutOfMemoryError}. + *

+ * Customizing the retention policy can happen only by providing a custom {@link java.util.Collection} implementation + * to the {@link #distinct(Function, Callable)} overload. *

*
Scheduler:
*
{@code distinct} does not operate by default on a particular {@link Scheduler}.
@@ -7045,6 +7079,7 @@ public final Observable distinct() { * is distinct from another one or not * @return an Observable that emits those items emitted by the source ObservableSource that have distinct keys * @see ReactiveX operators documentation: Distinct + * @see #distinct(Function, Callable) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -7054,9 +7089,14 @@ public final Observable distinct(Function keySelector) { /** * Returns an Observable that emits all items emitted by the source ObservableSource that are distinct according - * to a key selector function. + * to a key selector function and based on {@link Object#equals(Object)} comparison of the objects + * returned by the key selector function. *

* + *

+ * It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} + * and {@link Object#hashCode()} to provide meaningful comparison between the key objects as + * the default Java implementation only considers reference equivalence. *

*
Scheduler:
*
{@code distinct} does not operate by default on a particular {@link Scheduler}.
@@ -7082,9 +7122,18 @@ public final Observable distinct(Function keySelector, Call /** * Returns an Observable that emits all items emitted by the source ObservableSource that are distinct from their - * immediate predecessors. + * immediate predecessors based on {@link Object#equals(Object)} comparison. *

* + *

+ * It is recommended the elements' class {@code T} in the flow overrides the default {@code Object.equals()} to provide + * meaningful comparison between items as the default Java implementation only considers reference equivalence. + * Alternatively, use the {@link #distinctUntilChanged(BiPredicate)} overload and provide a comparison function + * in case the class {@code T} can't be overridden with custom {@code equals()} or the comparison itself + * should happen on different terms or properties of the class {@code T}. + *

+ * Note that the operator always retains the latest item from upstream regardless of the comparison result + * and uses it in the next comparison with the next upstream item. *

*
Scheduler:
*
{@code distinctUntilChanged} does not operate by default on a particular {@link Scheduler}.
@@ -7093,6 +7142,7 @@ public final Observable distinct(Function keySelector, Call * @return an Observable that emits those items from the source ObservableSource that are distinct from their * immediate predecessors * @see ReactiveX operators documentation: Distinct + * @see #distinctUntilChanged(BiPredicate) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -7102,9 +7152,20 @@ public final Observable distinctUntilChanged() { /** * Returns an Observable that emits all items emitted by the source ObservableSource that are distinct from their - * immediate predecessors, according to a key selector function. + * immediate predecessors, according to a key selector function and based on {@link Object#equals(Object)} comparison + * of those objects returned by the key selector function. *

* + *

+ * It is recommended the keys' class {@code K} overrides the default {@code Object.equals()} to provide + * meaningful comparison between the key objects as the default Java implementation only considers reference equivalence. + * Alternatively, use the {@link #distinctUntilChanged(BiPredicate)} overload and provide a comparison function + * in case the class {@code K} can't be overridden with custom {@code equals()} or the comparison itself + * should happen on different terms or properties of the item class {@code T} (for which the keys can be + * derived via a similar selector). + *

+ * Note that the operator always retains the latest key from upstream regardless of the comparison result + * and uses it in the next comparison with the next key derived from the next upstream item. *

*
Scheduler:
*
{@code distinctUntilChanged} does not operate by default on a particular {@link Scheduler}.
@@ -7130,6 +7191,9 @@ public final Observable distinctUntilChanged(Function keySe * immediate predecessors when compared with each other via the provided comparator function. *

* + *

+ * Note that the operator always retains the latest item from upstream regardless of the comparison result + * and uses it in the next comparison with the next upstream item. *

*
Scheduler:
*
{@code distinctUntilChanged} does not operate by default on a particular {@link Scheduler}.