Skip to content

Instantly share code, notes, and snippets.

@ktejnora
Created January 21, 2015 21:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save ktejnora/98c736212ddd023ce420 to your computer and use it in GitHub Desktop.
Save ktejnora/98c736212ddd023ce420 to your computer and use it in GitHub Desktop.
Java 8 Create list of pairs from List of items. Java does not have Pair and groupBy uses AtomicInteger trick.
package cz.tejnora.pokusy;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Test;
public class ExampleUnitTest {
public <T> List<Pair<T, T>> toPairs(final Stream<T> s) {
final AtomicInteger counter = new AtomicInteger(0);
return s.collect(
Collectors.groupingBy(item -> {
final int i = counter.getAndIncrement();
return (i % 2 == 0) ? i : i - 1;
})).values().stream().map(a -> new Pair<T, T>(a.get(0), (a.size() == 2 ? a.get(1) : null)))
.collect(Collectors.toList());
}
@Test
public void testOdd() {
final List<String> s = Arrays.asList("a1", "a2", "b1", "b2", "c");
final Iterator<Pair<String, String>> iterator = toPairs(s.stream()).iterator();
assertThat(iterator.next(), is(pair("a1", "a2")));
assertThat(iterator.next(), is(pair("b1", "b2")));
assertThat(iterator.next(), is(pair("c", null)));
assertThat(iterator.hasNext(), is(false));
}
@Test
public void testEven() {
final List<String> s = Arrays.asList("a1", "a2", "b1", "b2", "c1", "c2");
final Iterator<Pair<String, String>> iterator = toPairs(s.stream()).iterator();
assertThat(iterator.next(), is(pair("a1", "a2")));
assertThat(iterator.next(), is(pair("b1", "b2")));
assertThat(iterator.next(), is(pair("c1", "c2")));
assertThat(iterator.hasNext(), is(false));
}
@Test
public void testEmpty() {
final List<String> s = Collections.emptyList();
final List<Pair<String, String>> r = toPairs(s.stream());
assertThat(r, is(s));
}
static final <F, S> Pair<F, S> pair(final F f, final S s) {
return new Pair<>(f, s);
}
static class Pair<F, S> {
final F fst;
final S snd;
public Pair(final F l, final S r) {
fst = l;
snd = r;
}
@Override
public String toString() {
return "(" + fst + ", " + snd + ")";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((fst == null) ? 0 : fst.hashCode());
result = prime * result + ((snd == null) ? 0 : snd.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Pair<?, ?> other = (Pair<?, ?>) obj;
if (fst == null) {
if (other.fst != null) {
return false;
}
} else if (!fst.equals(other.fst)) {
return false;
}
if (snd == null) {
if (other.snd != null) {
return false;
}
} else if (!snd.equals(other.snd)) {
return false;
}
return true;
}
}
}
@cmadsen
Copy link

cmadsen commented Dec 13, 2018

groupingBy needs to use LinkedHashMap to preserve ordering.

groupingBy(item -> {
			final int i = counter.getAndIncrement();
			return (i % 2 == 0) ? i : i - 1;
		}, LinkedHashMap::new, Collectors.toList())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment