Skip to content

Instantly share code, notes, and snippets.

@dexterous
Created June 3, 2025 21:11
Show Gist options
  • Save dexterous/543c4d66e1f4cc7dabdaf16a6b6c09bd to your computer and use it in GitHub Desktop.
Save dexterous/543c4d66e1f4cc7dabdaf16a6b6c09bd to your computer and use it in GitHub Desktop.
Tap pattern in Java using Functional Interfaces
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
class Employee {
private Set<Org> orgs;
private Org primaryOrg;
public Org getPrimaryOrg() { return primaryOrg; }
public void setOrgs(final Set<Org> orgs) {
this.orgs = orgs;
if (!orgs.isEmpty()) {
this.primaryOrg = Collections.max(orgs);
}
}
public String toString() {
return String.format(
"Employee[%s]",
orgs.parallelStream().
map(o -> String.format("%s%s", o.equals(primaryOrg) ? "^" : "", o) ).
collect(Collectors.joining(", "))
);
}
public int hashCode() { return Objects.hash(orgs, primaryOrg); }
public boolean equals(final Object other) {
return other != null &&
other.getClass() == Employee.class &&
(this == other || this.equals((Employee) other));
}
private boolean equals(final Employee other) {
return other != null &&
(this == other ||
(this.orgs.equals(other.orgs) &&
this.primaryOrg.equals(other.primaryOrg)));
}
}
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
import java.util.Objects;
class Main {
public static void main(String[] args) {
System.console().printf("%n");
System.console().printf(
"%s%n",
Tap.sNew(Employee.class).with(e -> {
Tap<Org> newOrg = Tap.sNew(Org.class);
e.setOrgs(Set.of(
newOrg.with(o -> o.setCode("Thoughtworks")),
newOrg.with(o -> o.setCode("Grainger"))
));
})
);
System.console().printf("%n");
UnaryOperator<Integer> doubler = (Integer n) -> n * 2;
// wrap tap in a static method to void having to invoke apply(...)
System.console().printf("%d%n",
printap("Result").apply(
doubler.
compose(printap("Before")).
andThen(printap("After" )).
apply(10)
)
);
System.console().printf(
"%s%n", Objects.toString(Tap.s(new Org()).with(o -> o.setCode("Foo"))));
}
// XXX: Not generified as format string assumes object is decimal
private static UnaryOperator<Integer> printap(String message) {
return Tap.ped((Integer n) -> System.console().printf("%6s... %d%n", message, n));
}
}
class Org implements Comparable<Org> {
private String code;
public void setCode(String code) { this.code = code; }
public int compareTo(Org other) {
return this.code.compareTo(other.code);
}
public String toString() { return String.format("Org[code=%s]", code); }
public int hashCode() { return code.hashCode(); }
public boolean equals(final Object other) {
return other != null &&
other.getClass() == Org.class &&
(this == other || this.equals((Org) other));
}
private boolean equals(final Org other) {
return other != null &&
(this == other || this.code.equals(other.code));
}
}
import java.lang.reflect.Constructor;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
// XXX: Does Tap inherit @FunctionalInterface from Supplier?
// XXX: Does it make sense for a Tap to be a Callable?
public interface Tap<T> extends Supplier<T>, Callable<T> {
public static <T> Tap<T> ping(final T object) {
return s(object);
}
public static <T> Tap<T> s(final T object) {
return () -> object;
}
public static <T> Tap<T> sNew(final Class<T> clazz) {
// XXX: Well, this sucks balls.
Constructor<T> ctor;
try {
ctor = clazz.getDeclaredConstructor();
} catch (NoSuchMethodException x) {
throw new IllegalArgumentException(
String.format("{} has does not have a no-arg constructor.", clazz), x);
}
return ctor::newInstance;
/*
//TODO: Consider supporting ctor args
return () -> {
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (final Exception x) {
// TODO: Do better handing of x; What _could_ we even do here?
return null;
}
};
*/
}
public static <T> UnaryOperator<T> ped(final Consumer<? super T> tapper) {
return (final T target) -> Tap.s(target).with(tapper);
}
public default T get() {
try {
return this.call();
} catch (final Exception x) {
// TODO: Do better handing of x; What _could_ we even do here?
return null;
}
}
// TODO: consider if we should return Optional<T>
// XXX: we shouldn't; we support tapping nulls
public default T with(final Consumer<? super T> tapper) {
final T target = this.get();
Optional.ofNullable(target).ifPresent(tapper);
return target;
}
// XXX: original implementation of a bare basic tap function
// Source: https://dzone.com/articles/tap-that-assignment-with-java
public static <T> T tap(T object, Consumer<T> consumer) {
consumer.accept(object);
return object;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment