Primitive containsAny & containsNone in Eclipse Collections
When Eclipse Collections 11.0.0 is released, it will now include the containsAny
and containsNone
methods on its primitive collections.
The functionality offered by these methods was previously available through the use of the anySatisfy
and noneSatisfy
methods. However, the new methods will have performance benefits baked in and offer some new method signatures.
Overview
Only int
will be used for demonstration purposes in this article, but these are available for all of the other primitive collections.
The type signatures for these new methods are:
boolean containsAny(int… source)
boolean containsAny(IntIterable source)
boolean containsNone(int… source)
boolean containsNone(IntIterable source)
These methods are also tuned for performance when dealing with larger collection sizes. In those circumstances if the calling collection isn’t a Set
, then a Set
will be created to improve the speed of the lookup operations. A memory cost will be incurred to improve the overall performance of these methods.
default boolean containsAny(int... source)
{
IntIterable inside = this;
if (this.size() > 32 && source.length > 32 && !(this instanceof IntSet))
{
inside = this.toSet();
}
for (int i = 0; i < source.length; i++)
{
if (inside.contains(source[i]))
{
return true;
}
}
return false;
}
Above is the snippet for containsAny
, but the containsNone
is identical except for the return statements being swapped.
Happy Accidents
One awesome aspect of contributing to open source is that there are often side effects that make themselves known when you set out to do the work. As a result, there were a couple of things I was able to improve that weren’t explicitly defined in my ticket.
Performance of containsAll
As part of my original merge request, it was noted that the current implementation of containsAll
was badly implemented and runs in O(n²). With the help of one of the committers, I ended up optimizing the method as part of a different merge request. The optimization was incredible when running an acceptance test with two lists containing a million elements each. On my machine the old implementation took 110 seconds, while the new implementation only took 200 milliseconds. Yet another performance improvement you can look forward to in Eclipse Collections 11.0.0!
Bug in noneSatisfy
implementation of ImmutableBooleanEmptySet
When testing the containsAny
and containsNone
changes, I chanced across another bug that had to do with the return type of noneSatisfy
on the ImmutableBooleanEmptySet
object. My test assertions were not being honored, so when I dug into the code base I noticed that for this object the return type for both noneSatisfy
and anySatisfy
was false
! This should definitely not be the case since they are direct opposites. Luckily my tests exposed this inconsistency and I was able to include this fix as part of my merge request.
This whole experience was a nice reminder for me that open source benefits contributors and projects equally. An active and open project culture helps find bugs and performance issues by illuminating sections of code that might not have been looked at in long time.