Evolving the design of Eclipse Collections through symmetry.
Find the Missing Types
Eclipse Collections has a bunch of new types you will not find in the JDK. These types give developers useful functionality that they need. There is an extra cost to supporting additional container types, especially when you factor in having support for primitive types across these types.
These missing types are important. They help Eclipse Collections return better return types for iteration patterns.
Eclipse Collections has pretty good symmetry between object and primitive types.
The missing container types are fixed sized primitive arrays, primitive BiMaps, primitive Multimaps, and some of the primitive Intervals (only IntInterval exists today). String really only should exist as a primitive immutable collection of either char or int. Eclipse Collections has CharAdapter, CodePointAdapter and CodePointList which provide a rich set of iteration protocols that work with Strings.
There is still much that can be done to improve the symmetry between the object and primitive APIs. There are some APIs that cannot be replicated without adding new types. For instance, it would be less than desirable to implement a primitive version of groupBy with the current Multimap implementations because the only option would be to box the primitive Lists, Sets or Bags. Since there are a large number of APIs in Eclipse Collections, I will only draw attention to some of the major APIs that do not currently have symmetry between object and primitive collections. The following methods are missing on the primitive iterables.
- groupBy / groupByEach
- countBy / countByEach
- aggregateBy / aggregateInPlaceBy
- reduce / reduceInPlace
- All “With” methods
Of all the missing APIs on primitive collections perhaps the most subtle and yet glaring difference is the lack of “With” methods. It is not clear if the “With” methods would be as useful for primitive collections as they are with object collections. For some usage examples of the “With” methods on the object collection APIs, read my blog titled “Preposition Preference”. The “With” methods allow for more APIs to be used with Method References.
This is what the signatures for some of the “With” methods might look like on IntList.
<P> boolean anySatisfyWith(IntObjectPredicate<? super P> predicate, P parameter);<P> boolean allSatisfyWith(IntObjectPredicate<? super P> predicate, P parameter);<P> boolean noneSatisfyWith(IntObjectPredicate<? super P> predicate, P parameter);<P> IntList selectWith(IntObjectPredicate<? super P> predicate, P parameter);<P> IntList rejectWith(IntObjectPredicate<? super P> predicate, P parameter);
Default Methods to the Rescue
The addition of default methods in Java 8 has been of tremendous help increasing the symmetry between our object and primitive APIs. In Eclipse Collections 10.x we will be able to leverage default methods even more, as we now have the ability to use container factory classes in interfaces. The following examples show how the default implementations of countBy and countByWith has been optimized using the Bags factory.
default <V> Bag<V> countBy(Function<? super T, ? extends V> function)
return this.countBy(function, Bags.mutable.empty());
}default <V, P> Bag<V> countByWith(Function2<? super T, ? super P, ? extends V> function, P parameter)
return this.countByWith(function, parameter,
More on Eclipse Collections API design
You can also find a set of visualizations of the Eclipse Collection library in this blog post.