For debugging purposes I am trying to create string representations of lambda expressions (specifically of Predicate
s, though it would be interesting for other lambda expressions too) in Java 8. My idea would be something like this:
public class Whatever {
private static <T> String predicateToString(Predicate<T> predicate) {
String representation = ... // do magic
return representation;
}
public static void main(String[] args) {
System.out.println(Whatever.<Integer>predicateToString(i -> i % 2 == 0));
}
}
And the output would be i -> i % 2 == 0
(or something logically equivalent). The toString()
method seems to be of no help, the output is just something like com.something.Whatever$$Lambda$1/1919892312@5e91993f
(which I guess is to be expected as toString()
is not overridden).
I'm not sure whether something like this is even possible, e.g. with reflection, I certainly haven't been able to find anything on it so far. Any ideas?
The simplest thing I could come up with is creating a "named predicate" that gives your predicates a name or description, basically anything that will be useful as a toString
:
public class NamedPredicate<T> implements Predicate<T> {
private final String name;
private final Predicate<T> predicate;
public NamedPredicate(String name, Predicate<T> predicate) {
this.name = name;
this.predicate = predicate;
}
@Override
public boolean test(T t) {
return predicate.test(t);
}
@Override
public String toString() {
return name;
}
public static void main(String... args) {
Predicate<Integer> isEven = new NamedPredicate<>("isEven", i -> i % 2 == 0);
System.out.println(isEven); // prints isEven
}
}
Arguably giving your predicates names or descriptions like this makes the code where you use them a bit easier to understand also:
Stream.of(1, 2, 3, 4)
.filter(isEven)
.forEach(System.out::println);
A stranger idea might be to derive a "structural" description of the predicate, i.e. what is the output for some given inputs? Obviously this would work best when the input set is finite and small (e.g. for enums, booleans or some other restricted set), but I guess you could try a small set of "random" integers for integer predicates as well:
private static Map<Boolean, List<Integer>> testPredicate(Predicate<Integer> predicate) {
return Stream.of(-35, -3, 2, 5, 17, 29, 30, 460)
.collect(Collectors.partitioningBy(predicate));
}
For isEven
, this would return something like {false=[-35, -3, 5, 17, 29], true=[2, 30, 460]}
, which I don't think is necessarily clearer than if you manually give them a description, but is perhaps useful for predicates that are not under your control.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With