Eclipse Collections by Example: InjectInto
Learn one of the most general, flexible, and least understood iteration patterns in Eclipse Collections.
Continuum Transfunctioner
Like the Continuum Transfunctioner from “Dude, Where’s my car”, the method injectInto
is a very mysterious and powerful method, and its mystery is only exceeded by its power.
So what does injectInto do?
The method injectInto
can be used to do pretty much anything. The method injects an initial value into a two argument function along with the first element of the collection, and calculates some result. That result is then passed to the next invocation of the function as the initial value along with the next element of the collection. And so on and so forth until all elements of the collection have been visited and a final result is returned.
The name injectInto is based on the inject:into:
selector from Smalltalk. InjectInto
is an alternative name for foldLeft
or reduce
.
I will illustrate ways to implement various algorithms using injectInto
to show how mysterious and powerful it is.
Example: Min and Max
@Test
public void injectIntoMinAndMax()
{
MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5);
Integer maxInt = Integer.MAX_VALUE;
Integer minValue = list.injectInto(maxInt, Math::min);
Assert.assertEquals(list.min(), minValue);
Integer minInt = Integer.MIN_VALUE;
Integer maxValue = list.injectInto(minInt, Math::max);
Assert.assertEquals(list.max(), maxValue);
}
Example: Sum
@Test
public void injectIntoSum()
{
MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5);
Integer sum = list.injectInto(Integer.valueOf(0), Integer::sum);
Assert.assertEquals(Integer.valueOf(15), sum);
}
Example: Product
@Test
public void injectIntoProduct()
{
MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5);
Integer product =
list.injectInto(
Integer.valueOf(1),
(result, each) -> result * each);
Assert.assertEquals(Integer.valueOf(120), product);
}
Example: Collect
@Test
public void injectIntoCollect()
{
MutableList<String> lowerCase =
Lists.mutable.with("a", "b", "c", "d", "e");
MutableList<Object> upperCase =
lowerCase.injectInto(
Lists.mutable.empty(),
(list, each) -> list.with(each.toUpperCase()));
Assert.assertEquals(
lowerCase.collect(String::toUpperCase),
upperCase);
}
Example: GroupBy
@Test
public void injectIntoGroupBy()
{
MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5);
MutableListMultimap<Integer, Integer> grouped =
Multimaps.mutable.list.empty();
list.injectInto(grouped, (multimap, each) -> {
multimap.put(each % 2, each);
return multimap;
});
Assert.assertEquals(list.groupBy(each -> each % 2), grouped);
}
Example: Collectors.groupingBy
@Test
public void injectIntoGroupingBy()
{
MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5);
MutableMap<Integer, List<Integer>> grouped =
Maps.mutable.empty();
list.injectInto(grouped, (map, each) -> {
map.getIfAbsentPut(each % 2,Lists.mutable::empty)
.add(each);
return map;
});
Assert.assertEquals(
list.stream().collect(
Collectors.groupingBy(each -> each % 2)),
grouped);
}
Example: Detect
@Test
public void injectIntoDetect()
{
MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5);
Integer value = list.injectInto(
null,
(result, each) ->
result == null && each > 2 ? each : result);
Assert.assertEquals(list.detect(each -> each > 2), value);
}
Example: Select
@Test
public void injectIntoSelect()
{
MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5);
MutableList<Integer> value = list.injectInto(
Lists.mutable.empty(),
(result, each) ->
each % 2 == 0 ? result.with(each) : result);
Assert.assertEquals(list.select(each -> each % 2 == 0), value);
}
APIs covered in the examples
injectInto
— applies a two argument function to each element of a collection using an initial value, and then injecting the result of each application of the function into the next iteration.
Check out this presentation to learn more about the origins, design and evolution of the Eclipse Collections API.
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.