JDK java.util.concurrent.ConcurrentSkipListSet.equals(Object o) implementation efficiency
Jason Mehrens
jason_mehrens at hotmail.com
Fri May 26 16:51:26 UTC 2017
Tenghuan He,
You are correct if 'this' is a SortedMap/Set and 'o' is a SortedMap/Set then both interfaces list a clause in the top level documentation of:
"This order is reflected when iterating over the sorted map's collection views" and "The set's iterator will traverse the set in ascending element order."
So it should be safe to do an ordered 'list' type element comparison if and only if you have determined that both sets/maps use the same ordering.
In your example code you are missing the check to make sure the comparators are both null or equal.
Seems like a worthwhile RFE. In general, though I tend to think of use cases for ConcurrentSkipListSet as "wildly mutating" which means you never call Set equals
or equals fails pretty early due to the mutation.
Jason
________________________________________
From: core-libs-dev <core-libs-dev-bounces at openjdk.java.net> on behalf of Tenghuan He <tenghuanhe at gmail.com>
Sent: Friday, May 26, 2017 9:21 AM
To: core-libs-dev at openjdk.java.net
Subject: JDK java.util.concurrent.ConcurrentSkipListSet.equals(Object o) implementation efficiency
Hi, all
I found that the equalsimplementation of
java.util.concurrent.ConcurrentSkipListSet in JDK as follows:
public boolean equals(Object o) {
// Override AbstractSet version to avoid calling size()
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Collection<?> c = (Collection<?>) o;
try {
return containsAll(c) && c.containsAll(this);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}}
Since ConcurrentSkipListSet extends NavigableSet which extends SortedSet,
the following equalsimplementation seems more reasonable for a compare
object which also extends SortedSet.
public boolean myEquals(Object o) {
// Override AbstractSet version to avoid calling size()
if (o == this)
return true;
if (!(o instanceof Set))
return false;
if (o instanceof SortedSet) {
Iterator iter1 = ((SortedSet) o).iterator();
Iterator iter2 = iterator();
while (iter1.hasNext() && iter2.hasNext()) {
if (!iter1.next().equals(iter2.next())) {
return false;
}
}
return !(iter1.hasNext() || iter1.hasNext());
}
Collection<?> c = (Collection<?>) o;
try {
return containsAll(c) && c.containsAll(this);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}
A simple test has shown the performance improvement
public class Test {
public static void main(String[] args) {
ConcurrentSkipListSet<Integer> set1 = new
ConcurrentSkipListSet<Integer>();
ConcurrentSkipListSet<Integer> set2 = new
ConcurrentSkipListSet<Integer>();
for (int i = 0; i < 10000000; i++) {
set1.add(i);
set2.add(i);
}
long ts = System.currentTimeMillis();
System.out.println(set1.equals(set2));
System.out.println(System.currentTimeMillis() - ts);
ts = System.currentTimeMillis();
System.out.println(myset1.myEquals(myset2));
System.out.println(System.currentTimeMillis() - ts);
}}
Output result
true2713true589
Any ideas? (Related question on SO:
https://stackoverflow.com/questions/44198103/jdk-java-util-concurrent-concurrentskiplistset-equalsobject-o-implementation-e
Thanks & Best Regards
Tenghuan He
More information about the core-libs-dev
mailing list