-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Closed
Milestone
Description
distinctUntilChanged keeps the last value/key (depending on the overload) so it can compare it agains the newer value/key via Object.equals. However, if the value/key is mutable and gets mutated in between elements, the operator may not work as expected and filter out the seemingly same data:
PublishSubject<List<Integer>> subject = PublishSubject.create();
List<Integer> list = new ArrayList<Integer>();
list.add(1);
subject.distinctUntilChanged().subscribe(System.out::println);
subject.onNext(list);
// prints [1]
list.add(2);
subject.onNext(list);
// does not print anything, but [1, 2] was expected.In the example, the same reference is passed to distinctUntilChanged thus two subsequent items evaluate as same. This mistake by the user is also very common on Android and with text components using a mutable CharSequence.
I suggest adding a section to every distinctUntilChanged variant explaining the situation in short, something along the lines:
<p>
Note that if the element type of the flow is mutable, the comparison of the previous and current
item may yield unexpected results if the items are mutated externally. Common cases are mutable
{@code CharSequence}s or {@code List}s where subsequent objects are actually the same
references modified before/after {@code distinctUntilChanged}. It is recommended mutable data is
converted to an immutable one, such as `map(CharSequence::toString)` or
`map(Collections::unmodifiableList)` for example, to avoid the situation.
argestes and ankitChandora