Mysterious Eclipse Collections APIs: forEachInBoth

Donald Raab
Jun 26 · 3 min read

Sometimes APIs go undiscovered for a long time

What is Stonehenge?

Have you ever heard of forEachInBoth?

There is a method named forEachInBoth available in Eclipse Collections, but it can only be found on four utility classes. You can find the method on ArrayIterate, ListIterate, RandomAccessListIterate and ArrayListIterate.

The method forEachInBoth, takes two Lists or Arrays of the same size and iterates over both of them passing the elements from both lists at particular indexes into a two argument procedure.

The method has not been promoted to the ListIterable API in Eclipse Collections. This is probably because you can now zip two lists together and just use forEach or any of the other rich APIs from MutableList instead.

The Method Signatures

The method signatures for forEachInBoth on ListIterate, RandomAccessListIterate and ArrayListIterate are very similar so I will only show the signatures for ListIterate and ArrayIterate.

ListIterate

public static <T1, T2> void forEachInBoth(
List<T1> list1,
List<T2> list2,
Procedure2<? super T1, ? super T2> procedure)

ArrayIterate

public static <T1, T2> void forEachInBoth(
T1[] objectArray1,
T2[] objectArray2,
Procedure2<? super T1, ? super T2> procedure)

When is forEachInBoth useful?

One example that I discovered that forEachInBoth works well with is for converting two separate lists or arrays into a Map. Using forEachInBoth, I am able to use a method reference for calling put on the map instance. This was unexpectedly cool.

Putting two lists into a Map

The Source

@Test
public void forEachInBothList()
{
List<Integer> one =
Lists.mutable.with(1, 2, 3);
List<String> two =
Lists.mutable.with("One", "Two", "Three");
Map<Integer, String> map = Maps.mutable.empty();

ListIterate.forEachInBoth(one, two, map::put);

Assert.assertEquals(
Maps.mutable.with(1, "One", 2, "Two", 3, "Three"),
map);
}

This could easily work with two arrays of the same size using ArrayIterate instead.

What about zip?

If you use zip instead, you can use the fluent API to convert the zipped Lists into a Map using toMap. However, I could not take an existing Map and iterate using forEach or each and call Map.put since I would be iterating over Pair instances that would need to have the the two component parts of the pairs extracted and passed in as the key and value parameters.

Zipping two lists and putting them into a Map using toMap

The Source

@Test
public void zipList()
{
MutableList<Integer> one =
Lists.mutable.with(1, 2, 3);
MutableList<String> two =
Lists.mutable.with("One", "Two", "Three");

MutableMap<Integer, String> map =
one.zip(two).toMap(Pair::getOne, Pair::getTwo);

Assert.assertEquals(
Maps.mutable.with(1, "One", 2, "Two", 3, "Three"),
map);
}

In the case of zip with this example, there is a temporary List created after zip is called, but it will be garbage collected after the call to toMap since the List is not referenced anywhere. This same code can be implemented lazily by calling asLazy before calling zip. This removes the temporary List creation.

MutableMap<Integer, String> map =
one.asLazy()
.zip(two)
.toMap(Pair::getOne, Pair::getTwo);

When to use forEachInBoth or zip?

The primary benefit of forEachInBoth is that it is located in static utility and will work directly with Java arrays and any java.util.List. So if you need to convert two JDK Lists quickly into a Map, it might just be what the doctor ordered. However, because the method forEachInBoth returns void, you will not be able to make fluent methods calls like you can using zip. Most of the time, you may find zip more useful when dealing with two lists especially if you are performing multiple operations on the result.

If you discover a novel use case where forEachInBoth works well, please let us know by creating an issue on GitHub. We could move forEachInBoth up directly to the ListIterable API if there prove to be more good use cases that we just haven’t seen yet.

Eclipse Collections is open for contributions. If you like the library, you can let us know by starring it on GitHub.

Donald Raab

Written by

Java Champion. Creator of the Eclipse Collections OSS Java library (http://www.eclipse.org/collections/). Inspired by Smalltalk. Opinions are my own.