Eclipse Collections by Example: FlatCollect
Learn how to flatten a collection of collections into a single collection using the flatCollect
method in Eclipse Collections.
What is FlatCollect?
The method flatCollect
is a special form of collect
, where the output of the Function
provided to the method must always be some Iterable
type. The purpose of flatCollect
is to provide a transformation that flattens a collection of collections. This method is similar in function to flatMap
in Java Streams. The primary difference is that the Function
for flatCollect
must return an Iterable
, while the Function
for flatMap
must return a Stream
.
FlatCollecting a List (Java 8)
@Test
public void flatCollectingAListJava8()
{
MutableList<Integer> list = mList(5, 4, 3, 2, 1);
MutableList<Integer> result = list.flatCollect(Interval::oneTo);
MutableList<Integer> expected = mList(
1, 2, 3, 4, 5,
1, 2, 3, 4,
1, 2, 3,
1, 2,
1);
Assert.assertEquals(expected, result);
}
Collection Pipelines
Martin Fowler describes the Collection Pipeline pattern here. Here is an example of flatCollect
used in a collection pipeline to find all of the methods that contain “flat” in their name for a List of classes. Here I used a overloaded form of flatCollect
which takes a target collection as an argument.
@Test
public void flatCollectingAListOfMethodsToASetJava8()
{
MutableList<Class<?>> list = mList(
ListIterable.class,
MutableList.class,
ImmutableList.class);
MutableSet<String> result = list
.collect(Class::getMethods)
.flatCollect(Lists.fixedSize::with, mSet())
.collect(Method::getName)
.select(each -> each.toLowerCase().contains("flat"));
MutableSet<String> expected = mSet("flatCollect");
Assert.assertEquals(expected, result);
}
The method getMethods
on class returns an array, so in the Function
I pass to flatCollect
, I convert the array to a List
. If getMethods
had returned a List
or some other Iterable
type, I could have simply used flatCollect
passing Class::getMethods
.
Here’s the same example using Java 10 with Local-variable Type Inference.
@Test
public void flatCollectingAListOfMethodsToASetJava10()
{
var list = mList(
ListIterable.class,
MutableList.class,
ImmutableList.class);
var resultSet = list
.collect(Class::getMethods)
.flatCollect(Lists.fixedSize::with, mSet())
.collect(Method::getName)
.select(each -> each.toLowerCase().contains("flat"));
var expected = mSet("flatCollect");
Assert.assertEquals(expected, resultSet);
}
Symmetric Sympathy Strikes Again
While there exists a method named collectWith
which is a form of collect
that takes a Function2
, there currently is no method named flatCollectWith
which also takes a Function2
. I discovered the lack of flatCollectWith
(again) this week. I have submitted an issue for this feature and began working on it over the weekend. I expect to have the flatCollectWith
implementation tested and completed over the next week or two.
APIs covered in the examples
flatCollect
— transforms elements of a source collection to a new collection by flattening collections in the source collection to a single collectionmList
— creates aMutableList
mSet
— creates aMutableSet
Interval.oneTo(int)
— creates an Interval starting from 1 to the specified valuevar
— Local variable Type Inference included in Java 10 (JEP 286)
Refer to my previous blogs in the EC by Example series for examples of collect
and select
.
Check out this presentation to learn more about the origins, design and evolution of the Eclipse Collections API. There is also a video covering the slides that was recorded at an Eclipse Community Virtual Meet-up.
Eclipse Collections is open for contributions. If you like the library, you can let us know by starring it on GitHub.