Skip to content

Instantly share code, notes, and snippets.

@andrewrlee
Created November 16, 2016 22:49
Show Gist options
  • Save andrewrlee/2dd35df2c42a164f571e446c164642c0 to your computer and use it in GitHub Desktop.
Save andrewrlee/2dd35df2c42a164f571e446c164642c0 to your computer and use it in GitHub Desktop.
package uk.co.optimisticpanda.functionutils.pairs;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
public class Pairs {
public static <T, U> Function<T, Pair<T, U>> with(Supplier<U> supplier) {
return t -> Pair.of(t, supplier.get());
}
public static <S, T, U> Function<S, Triple<S, T, U>> with(Function<S, T> t, Function<S, U> u) {
return s -> Triple.of(s, t.apply(s), u.apply(s));
}
public static <T, U> Function<T, Pair<T, U>> with(Function<T, U> f) {
return val -> Pair.of(val, f.apply(val));
}
public static <T, U> Function<T, Stream<Pair<T, U>>> withOptional(Function<T, Optional<U>> f) {
return val -> f.apply(val).map(r -> Stream.of(Pair.of(val, r))).orElseGet(Stream::empty);
}
public static <T, U, R> Function<Pair<T, U>, R> from(BiFunction<T, U, R> f) {
return pair -> f.apply(pair.getLeft(), pair.getRight());
}
public static <S, T, U, R> Function<Triple<S, T, U>, R> from(TripleFunction<S, T, U, R> f) {
return pair -> f.apply(pair.getLeft(), pair.getMiddle(), pair.getRight());
}
@FunctionalInterface
public static interface TripleFunction<S, T, U, R> {
R apply(S s, T t, U u);
}
}
package uk.co.optimisticpanda.functionutils.pairs;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static uk.co.optimisticpanda.functionutils.pairs.Pairs.from;
import static uk.co.optimisticpanda.functionutils.pairs.Pairs.with;
import static uk.co.optimisticpanda.functionutils.pairs.Pairs.withOptional;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.junit.Test;
import com.google.common.collect.ImmutableMap;
public class PairsTest {
private final Service service = new Service();
@Test
public void checkWithAndFrom(){
List<String> result = service.getNames().stream()
.map(with(service::getNameLength))
.map(from((name, length) -> name + " has length " + length))
.collect(toList());
assertThat(result).containsExactly(
"Sally has length 5",
"Andy has length 4",
"Bob has length 3");
}
@Test
public void checkWithSupplier(){
List<String> result = service.getNames().stream()
.map(with(() -> "HAPPY"))
.map(from((name, emotion) -> name + " is " + emotion))
.collect(toList());
assertThat(result).containsExactly(
"Sally is HAPPY",
"Andy is HAPPY",
"Bob is HAPPY");
}
@Test
public void checkFlatMapWithAndFrom(){
List<String> result = service.getNames().stream()
.flatMap(withOptional(service::getAge))
.map(from((name, length) -> name + " is " + length))
.collect(toList());
assertThat(result).containsExactly(
"Sally is 30",
"Bob is 29");
}
@Test
public void triple() {
List<String> result = service.getNames().stream()
.map(with(service::getNameLength, service::getNameUppercase))
.map(from((name, length, upper) -> format("%s has length %s (%s)", name, length, upper)))
.collect(toList());
assertThat(result).containsExactly(
"Sally has length 5 (SALLY)",
"Andy has length 4 (ANDY)",
"Bob has length 3 (BOB)");
}
private static class Service {
private final Map<String, Integer> map = ImmutableMap.of("Sally", 30, "Bob", 29);
private List<String> getNames() {
return asList("Sally", "Andy", "Bob");
}
private Integer getNameLength(String name) {
return name.length();
}
private String getNameUppercase(String name) {
return name.toUpperCase();
}
private Optional<Integer> getAge(String name) {
return Optional.ofNullable(map.get(name));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment