10 Features in Eclipse Collections 10.0
My Top 10 List
In this post, I will share my favorite ten features included in the Eclipse Collections 10.0 release.
1. Stream for Primitive Lists
Now you can call primitiveStream
on primitive Lists. The method primitiveStream is available on Int
, Long
and DoubleLists
.
@Test
public void primitiveListToPrimitiveStream()
{
IntStream intStream1 =
IntLists.mutable.with(1, 2, 3, 4, 5)
.primitiveStream();
IntStream intStream2 =
IntLists.immutable.with(1, 2, 3, 4, 5)
.primitiveStream();
LongStream longStream1 =
LongLists.mutable.with(1L, 2L, 3L, 4L, 5L)
.primitiveStream();
LongStream longStream2 =
LongLists.immutable.with(1L, 2L, 3L, 4L, 5L)
.primitiveStream();
DoubleStream doubleStream1 =
DoubleLists.mutable.with(1.0, 2.0, 3.0, 4.0, 5.0)
.primitiveStream();
DoubleStream doubleStream2 =
DoubleLists.immutable.with(1.0, 2.0, 3.0, 4.0, 5.0)
.primitiveStream();
}
2. toMap with a target Map
The method toMap
has been overloaded to allow a target map to be passed in as a parameter.
@Test
public void toMapWithTarget()
{
MutableList<Integer> list =
Lists.mutable.with(1, 2, 3, 4, 5);
Map<String, Integer> map =
list.toMap(String::valueOf,
each -> each,
new LinkedHashMap<>());
Map<String, Integer> expected = new LinkedHashMap<>();
expected.put("1", 1);
expected.put("2", 2);
expected.put("3", 3);
expected.put("4", 4);
expected.put("5", 5);
Assert.assertEquals(expected, map);
}
3. RichIterable toBiMap
With Eclipse Collections 10.0, you can now convert any RichIterable
to a BiMap
.
@Test
public void toBiMap()
{
MutableBiMap<String, Integer> expected =
BiMaps.mutable.with("1", 1, "2", 2, "3", 3);
MutableBiMap<String, Integer> biMap =
Lists.mutable.with(1, 2, 3).toBiMap(String::valueOf, i -> i);
Assert.assertEquals(expected, biMap);
}
4. fromStream on Collection Factories
We can now construct a Collection
from a Stream
using fromStream
on each of the Collection factories for List
, Set
, Bag
, and Stack
.
@Test
public void fromStreamOnCollectionFactories()
{
MutableList<Integer>
list = Lists.mutable.fromStream(Stream.of(1, 2, 3, 4, 5));
Assert.assertEquals(
Lists.mutable.with(1, 2, 3, 4, 5), list);
MutableSet<Integer> set =
Sets.mutable.fromStream(Stream.of(1, 2, 3, 4, 5));
Assert.assertEquals(
Sets.mutable.with(1, 2, 3, 4, 5), set);
MutableBag<Integer> bag =
Bags.mutable.fromStream(Stream.of(1, 2, 3, 4, 5));
Assert.assertEquals(
Bags.mutable.with(1, 2, 3, 4, 5), bag);
MutableStack<Integer> stack =
Stacks.mutable.fromStream(Stream.of(1, 2, 3, 4, 5));
Assert.assertEquals(
Stacks.mutable.with(1, 2, 3, 4, 5), stack);
}
5. MutableMultimap getIfAbsentPutAll
The method getIfAbsentPutAll
on a MutableMultimap
is equivalent to getIfAbsentPut
on a MutableMap
. The difference is that with a Multimap
you can put in multiple values.
@Test
public void getIfAbsentPutAll()
{
MutableListMultimap<Integer, Integer> multimap =
Multimaps.mutable.list.with(2, 1);
ImmutableList<Integer> defaultValue =
Lists.immutable.with(1, 2, 3);
MutableList<Integer> oneValue =
multimap.getIfAbsentPutAll(1, defaultValue);
MutableList<Integer> twoValue =
multimap.getIfAbsentPutAll(2, defaultValue);
Assert.assertEquals(defaultValue, oneValue);
Assert.assertEquals(Lists.mutable.with(1), twoValue);
}
6. Bag collectWithOccurrences
You can use this method to transform a collection using all of the unique items in the Bag
along with their counts. Specify 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);
}
7. 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));
}
8. 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"));
}
9. 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);
}
10. Convert Iterable to Primitive Collections
Before Eclipse Collections 10.0, if you wanted to convert an Iterable
of boxed primitive types to a primitive Collection
(e.g. Integer
-> int
), you would have to first convert the Iterable
to a Collection
or a Stream
. In the case of a Stream
, you could then use one of the stock primitive Collectors
in Collectors2
to convert to a primitive Collection
. Now you can use the following factory methods to convert from Iterable
of some boxed value like Integer
to a primitive Collection
. This works for all of the boxed primitive types, across all supported primitive Collection
types.
@Test
public void convertFromIterableToPrimitiveCollection()
{
Iterable<Integer> iterable = Interval.oneTo(5);
IntInterval intInterval = IntInterval.oneTo(5);
MutableIntList mIntList =
IntLists.mutable.withAll(iterable);
ImmutableIntList iIntList =
IntLists.immutable.withAll(iterable);
Assert.assertEquals(intInterval, mIntList);
Assert.assertEquals(intInterval, iIntList);
MutableIntSet mIntSet =
IntSets.mutable.withAll(iterable);
ImmutableIntSet iIntSet =
IntSets.immutable.withAll(iterable);
Assert.assertEquals(intInterval.toSet(), mIntSet);
Assert.assertEquals(intInterval.toSet(), iIntSet);
MutableIntBag mIntBag =
IntBags.mutable.withAll(iterable);
ImmutableIntBag iIntBag =
IntBags.immutable.withAll(iterable);
Assert.assertEquals(intInterval.toBag(), mIntBag);
Assert.assertEquals(intInterval.toBag(), iIntBag);
}
I hope you enjoy all of the new features in Eclipse Collections 10.0!
Eclipse Collections is open for contributions. If you like the library, you can let us know by starring it on GitHub.