New Features of Eclipse Collections 10.0 — Part 1

Donald Raab
4 min readJul 15, 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 of the twenty six new features mentioned in the Eclipse Collections 10.0 Release Summary Blog.

1. MultiReaderList/Bag/Set Interfaces

We have had multi-reader collection implementations for a long time. We have not had specialized interfaces for them. Now we do.

MultiReaderList/Set/Bag Interfaces
@Test
public void multiReaderList()
{
MultiReaderList<String> list =
Lists.multiReader.with("1", "2", "3");

list.withWriteLockAndDelegate(backingList -> {
Iterator<String> iterator = backingList.iterator();
iterator.next();
iterator.remove();
});
Assert.assertEquals(Lists.mutable.with("2", "3"), list);
}

2. Stream for Primitive Lists

You can ask for a Stream from a regular List, but prior to Eclipse Collections 10.0, you could not easily get a primitive Stream from a primitive List. Now you can.

@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();
}

3. toMap supports passing 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);
}

4. MutableMapIterable removeAllKeys

With Eclipse Collections 10.0, you can removeAllKeys from a Map that are contained in the specified Set parameter.

@Test
public void removeAllKeys()
{
MutableMap<Integer, String> map =
Maps.mutable.with(1, "1", 2, "2", 3, "3");

map.removeAllKeys(Sets.mutable.with(1, 3));

Assert.assertEquals(Maps.mutable.with(2, "2"), map);
}

5. 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);
}

6. MultiMap collectKeyMultiValues

We can now transform a Multimap applying functions to both keys and values using collectKeyMultiValues.

@Test
public void collecKeyMultiValues()
{
MutableListMultimap<String, String> multimap =
Multimaps.mutable.list.with(
"nj", "Monmouth",
"nj", "Bergen",
"nj", "Union");

MutableBagMultimap<String, String> transformed =
multimap.collectKeyMultiValues(
String::toUpperCase,
String::toUpperCase);

Assert.assertEquals(Multimaps.mutable.bag.with(
"NJ", "MONMOUTH",
"NJ", "BERGEN",
"NJ", "UNION"), transformed);
}

7. 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);
}

8. LazyIterate cartesianProduct

Sometimes it’s useful to calculate the cartesianProduct of more than just Sets. LazyIterate.cartesianProduct will take any Iterable.

@Test
public void cartesianProduct()
{
MutableList<Integer> numbers = Lists.mutable.with(1, 2, 3);
MutableList<String> letters = Lists.mutable.with("A", "B", "C");

MutableList<Pair<String, Integer>> pairs =
LazyIterate.cartesianProduct(letters, numbers).toList();

MutableList<Pair<String, Integer>> expected =
Lists.mutable.with(
Tuples.pair("A", 1),
Tuples.pair("A", 2),
Tuples.pair("A", 3),
Tuples.pair("B", 1),
Tuples.pair("B", 2),
Tuples.pair("B", 3),
Tuples.pair("C", 1),
Tuples.pair("C", 2),
Tuples.pair("C", 3));

Assert.assertEquals(expected, pairs);
}

9. Primitive Maps updateValues

In case you want to update all of the values in a primitive Map, now you can using updateValues.

@Test
public void updateValues()
{
MutableIntIntMap map = IntIntMaps.mutable.empty()
.withKeyValue(1, 5)
.withKeyValue(2, 3)
.withKeyValue(3, 10);

map.updateValues((k, v) -> v + 1);

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

Assert.assertEquals(expected, map);
}

10. 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);
}

Stay Tuned!

There are still sixteen more features to cover in Eclipse Collections 10.0. I will be writing two more blogs covering all 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