New Features of Eclipse Collections 10.0 — Part 2

Donald Raab
4 min readJul 22, 2019

--

Examples of ten new features in the latest major release of the Eclipse Collections library.

Ten new features in Eclipse Collections 10.0

Summary

In this blog I will cover ten more of the twenty six new features mentioned in the Eclipse Collections 10.0 Release Summary Blog. Part one of the feature blog series covered the first ten feature examples in Eclipse Collections 10.0.

11. Bag.collectWithOccurrences

You can use this method to transform a collection using all of the unique items in the Bag along with their counts. You specific an ObjectIntToObjectFunction to transform the items an their counts to some resulting object. In the following example, I will collect the items and their counts into ObjectIntPair instances.

@Test
public void collectWithOccurences()
{
MutableBag<String> source =
Bags.mutable.with("1", "2", "2", "3", "3", "3");

MutableBag<ObjectIntPair<String>> targetBag =
source.collectWithOccurrences(PrimitiveTuples::pair);

MutableBag<ObjectIntPair<String>> expected =
Bags.mutable.with(
PrimitiveTuples.pair("1", 1),
PrimitiveTuples.pair("2", 2),
PrimitiveTuples.pair("3", 3));

Assert.assertEquals(expected, targetBag);
}

12. Reduce / reduceIfEmpty for Primitive Iterables

The method reduce will apply a two argument (long, int) function which returns a long for each element of the collection. This allows for a widening of the result type so as not to overflow on functions like sum. In the case of an empty collection, a NoSuchElementException will be thrown.

@Test
public void reducePrimitiveIterables()
{
MutableIntList list =
IntLists.mutable.with(1, 2, 3, 4, 5);

long sum = list.reduce(Long::sum);

Assert.assertEquals(15L, sum);
Assert.assertEquals(list.sum(), sum);

Verify.assertThrows(
NoSuchElementException.class,
()-> IntLists.mutable.empty().reduce(Long::sum));
}

If you would like to safely handle the case of empty, you can use reduceIfEmpty and specify a default value to return.

@Test
public void reduceIfEmptyPrimitiveIterables()
{
MutableIntList list =
IntLists.mutable.with(1, 2, 3, 4, 5);

long sum = list.reduceIfEmpty(Long::sum, 0L);

Assert.assertEquals(15L, sum);
Assert.assertEquals(list.sum(), sum);

Assert.assertEquals(0L,
IntLists.mutable.empty()
.reduceIfEmpty(Long::sum, 0L));
}

13. New <T1><T2>To<T1>Function for primitives

In the reduce example above, the method reduce for an IntIterable takes a new interface names LongIntToLongFunction. There are two argument functions for every combination of every primitive type.

@Test
public void newLongTypeToLongFunctions()
{
MutableIntList intList =
IntLists.mutable.with(1, 2, 3, 4, 5);

LongIntToLongFunction sumFunction1 = Long::sum;
long sum1 = intList.reduceIfEmpty(sumFunction1, 0L);

Assert.assertEquals(15L, sum1);

MutableByteList byteList =
ByteLists.mutable.with((byte) 1, (byte) 2, (byte) 3);

LongByteToLongFunction sumFunction2 = Long::sum;
long sum2 = byteList.reduceIfEmpty(sumFunction2, 0L);

Assert.assertEquals(6L, sum2);
}

14. Of/withInitialCapacity to Primitive Maps

You can now construct a primitive map with an initial capacity using ofInitialCapacity or withInitialCapacity on the primitive map factories.

@Test
public void ofAndWithInitialCapacity()
{
MutableIntIntMap map1 =
IntIntMaps.mutable.ofInitialCapacity(100);

MutableIntIntMap map2 =
IntIntMaps.mutable.withInitialCapacity(100);

Assert.assertEquals(map1, map2);
}

15. RichIterable.countByEach

The method countByEach is similar to groupByEach and flatCollect. All three take a Function which returns an Iterable. The result in the case of countByEach is a Bag. In the following example, I count all of the methods by their names for three classes. The count of methods will include overloads and overrides of the methods.

@Test
public void countByEach()
{
MutableList<Class<?>> classes =
Lists.mutable.with(
RichIterable.class,
MutableList.class,
ImmutableList.class);

Bag<String> methodNames =
classes.countByEach(each ->
ArrayAdapter.adapt(each.getMethods())
.collect(Method::getName));

Assert.assertEquals(8,
methodNames.occurrencesOf("countByEach"));
Assert.assertEquals(16,
methodNames.occurrencesOf("groupByEach"));
Assert.assertEquals(2,
methodNames.occurrencesOf("sortThis"));
}

16. UnifiedSetWithHashingStrategy.addOrReplace

The method addOrReplace on a UnifiedSetWithHashingStrategy will replace a value in the Set if it already exists. This is different than calling add which will not replace a value in a Set if it already exists.

@Test
public void addOrReplace()
{
UnifiedSetWithHashingStrategy<Integer> set =
new UnifiedSetWithHashingStrategy<>(
HashingStrategies.defaultStrategy());
Integer one = new Integer(1);
set.addOrReplace(one);
Assert.assertSame(one, set.get(1));
set.add(new Integer(1));
Assert.assertSame(one, set.get(1));
Integer otherOne = new Integer(1);
set.addOrReplace(otherOne);
Integer integer = set.get(otherOne);
Assert.assertSame(otherOne, integer);
Assert.assertNotSame(one, integer);
}

17. UnmodifiableMutableOrderedMap

If you call asUnmodifiable() on a MutableOrderedMap, you will get an UnmodifiableMutableOrderedMap instance returned.

@Test
public void unmodifiableMutableOrderedMap()
{
MutableOrderedMap<Object, Object> map =
OrderedMaps.adapt(new LinkedHashMap<>())
.asUnmodifiable();

Verify.assertInstanceOf(
UnmodifiableMutableOrderedMap.class,
map);
}

18. WithAllKeyValues on mutable primitive maps

There is a new method on primitive maps that allows you to put multiple pairs of keys and values into the Map at once.

@Test
public void withAllKeyValues()
{
MutableIntIntMap map =
IntIntMaps.mutable.empty()
.withAllKeyValues(
Lists.mutable.with(
PrimitiveTuples.pair(1, 1),
PrimitiveTuples.pair(2, 2),
PrimitiveTuples.pair(3, 3)
))
.withAllKeyValues(
Lists.mutable.with(
PrimitiveTuples.pair(4, 4),
PrimitiveTuples.pair(5, 5)
));

MutableIntIntMap expected = IntIntMaps.mutable.empty()
.withKeyValue(1, 1)
.withKeyValue(2, 2)
.withKeyValue(3, 3)
.withKeyValue(4, 4)
.withKeyValue(5, 5);

Assert.assertEquals(expected, map);
}

19. Create Primitive Map from Iterable

You can now create a primitive Map from an Iterable with two provided Functions. One Function is used to calculate the key, and the other is used to calculate the value. This method is very similar the method toMap on RichIterable. The difference is that it works with any primitive Map.

@Test
public void createPrimitiveMapFromIterable()
{
Iterable<Integer> integers = Interval.oneTo(5);
MutableIntIntMap map =
IntIntMaps.mutable.from(
integers,
key -> key,
value -> value);

MutableIntIntMap expected = IntIntMaps.mutable.empty()
.withKeyValue(1, 1)
.withKeyValue(2, 2)
.withKeyValue(3, 3)
.withKeyValue(4, 4)
.withKeyValue(5, 5);

Assert.assertEquals(expected, map);
}

20. HashingStrategySets.of/withInitialCapacity

You can now create a HashingStrategySet using of or withInitialCapacity on the HashingStrategySets factory.

@Test
public void hashingStrategySetsOfOrWithInitialCapacity()
{
MutableSet<Object> set1 =
HashingStrategySets.mutable.ofInitialCapacity(
HashingStrategies.defaultStrategy(),
100);

MutableSet<Object> set2 =
HashingStrategySets.mutable.withInitialCapacity(
HashingStrategies.defaultStrategy(),
100);

Assert.assertEquals(set1, set2);
}

Stay Tuned!

There are still six more features to cover in Eclipse Collections 10.0. I will be writing one more blog covering the final set of them.

I hope you enjoy all of the new features in Eclipse Collections 10.0!

I am a Project Lead and Committer for the Eclipse Collections OSS project at the Eclipse Foundation. Eclipse Collections is open for contributions. If you like the library, you can let us know by starring it on GitHub.

--

--

Donald Raab
Donald Raab

Written by Donald Raab

Java Champion. Creator of the Eclipse Collections OSS Java library (https://github.com/eclipse/eclipse-collections). Inspired by Smalltalk. Opinions are my own.

No responses yet