New Features of Eclipse Collections 10.0 — Part 2
Examples of ten new features in the latest major release of the Eclipse Collections library.
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.