-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
java.util.Comparator is not suitable for distinct and distinctUntilChanged #395
Comments
those with custom equality are not yet there because of issue ReactiveX#395
The 'Func2' sounds fine unless 'getHashCode()' is necessary to make 'distinct()' fast. In that case I think making our own 'EqualComparator' would be the way to go. |
A int compare(T o1, T o2) http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html#compare(T,%20T)
Moving to Supporting Comparator (and Comparable object types) makes it so people can just reuse the same logic as used for ordering. Checking for equality is simpler than checking for ordering (binary instead of trinary response), but if the Comparator returns 0 it means the objects are equal. So if we're not going to use For example, the |
A
We don't actually need the total ordering for our purposes in As an aside, Also, at least for Imho, for doing this right, we actually need a real Java equivalent to |
The My vote is for |
The I agree, though, that it's probably a very limited use case. So I'm ok with |
Or maybe |
This is a valid concern, iterating the entire list is not good (though with a Comparator we could maintain a sorted list and do a binary search!). Another consideration for API design, an interface with 2 methods like Is this use case and performance issue strong enough to have a non-functional interface that requires an anonymous inner class to implement two methods? Also, implementing hashCode is far more obnoxious than implementing equals. For performance reasons and avoiding hashCode implementations, would How about this change to use final Subscription sourceSub = source.subscribe(new Observer<T>() {
// use TreeSet instead of ArrayList
private final TreeSet<U> emittedKeys = new TreeSet<U>(equalityComparator);
@Override
public void onCompleted() {
observer.onCompleted();
}
@Override
public void onError(Throwable e) {
observer.onError(e);
}
@Override
public void onNext(T next) {
U nextKey = keySelector.call(next);
if(emittedKeys.add(nextKey)) {
observer.onNext(next);
}
}
}); Unit Test: @Test
public void testDistinctOfObjectWithComparator() {
Observer<? super RandomObject> observer = mock(Observer.class);
RandomObject r1 = new RandomObject(1, "one");
RandomObject r2 = new RandomObject(2, "two");
RandomObject r2b = new RandomObject(2, "twoB");
Observable<RandomObject> src = from(r1, r1, r2, r1, r2, r2b);
create(distinct(src, new Comparator<RandomObject>() {
@Override
public int compare(RandomObject o1, RandomObject o2) {
int i = o1.i - o2.i;
if(i != 0) {
return i;
}
return o1.v.compareTo(o2.v);
}
})).subscribe(observer);
InOrder inOrder = inOrder(observer);
inOrder.verify(observer, times(1)).onNext(r1);
inOrder.verify(observer, times(1)).onNext(r2);
inOrder.verify(observer, times(1)).onNext(r2b);
inOrder.verify(observer, times(1)).onCompleted();
verify(observer, never()).onError(any(Throwable.class));
inOrder.verifyNoMoreInteractions();
} |
For It's not correct in Java to implement |
This method 'java.util.Objects.hash(Object...)' makes computing hash codes much easier. |
@jmhofer Yes, if it's not consistent with equals it won't work, but if they have equals they don't need to use @abersnaze Yes it does, but I'd like to avoid an API that requires developers to do that and know about some obscure API if we don't need it. Question about using |
If the observable objects already have an Java doesn't really support the concept of multiple equivalence relations per class. It would need something like the My current implementation is a bit inconsistent: It takes a The more I think about it, the more I agree with @samuelgruetter that the So basically, I'm for using a simple If we created an interface like |
We ended up removing |
those with custom equality are not yet there because of issue ReactiveX#395
Removing these fairly recently added overloads as they turn out to not be the best approach. Discussion ongoing as to how to implement them at ReactiveX#395
Removing these fairly recently added overloads as they turn out to not be the best approach. Discussion ongoing as to how to implement them at ReactiveX#395
In C#,
distinct
anddistinctUntilChanged
take anIEqualityComparer
(which providesEquals
andGetHashCode
).That's not the same as
java.util.Comparator
(which providescompare
).Or mathematically speaking: There are two kinds of comparators:
java.util.Comparator
and C#'sIComparer
IEqualityComparer
, RxJava'sFunc2<T, T, Boolean>
, and unfortunately no standard Java interfaceThe problem is that for
distinct
anddistinctUntilChanged
, we're not interested in an order on the elements, but only in equality.So it would be better to use
Func2<? super T, ? super T, Boolean> equality
(just likesequenceEqual
) instead ofComparator<U> equalityComparator
.The text was updated successfully, but these errors were encountered: