Creating a string representation of a lambda expression

For debugging purposes, I am trying to create string representations of lambda expressions (in particular, Predicate s, although that would be interesting for other lambda expressions) 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 result will be i -> i % 2 == 0 (or something logically equivalent). The toString() method does not seem to help, the output is something like com.something.Whatever$$Lambda$1/ 1919892312@5e91993f (which I suppose should be expected since toString() not overridden) .

I'm not sure if something like this is possible, for example. with reflection, of course, I could not find anything yet. Any ideas?

+6
source share
1 answer

The simplest thing I could come up with was to create a “named predicate” that gives your predicates a name or description, basically all that would 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 } } 

Perhaps your names or descriptions of your predicates make the code in which you use them a little easier to understand:

 Stream.of(1, 2, 3, 4) .filter(isEven) .forEach(System.out::println); 

An unfamiliar idea may be to obtain a “structural” description of the predicate, i.e. what is the result for some given inputs? Obviously, this will work best when the input set is finite and small (for example, for enumerations, Boolean or some other restricted sets), but I think you could try a small set of "random" integers for integer predicates:

 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 will return something like {false=[-35, -3, 5, 17, 29], true=[2, 30, 460]} , which, I think, will not necessarily be clearer than if You manually described them, but it may be useful for predicates that are not under your control.

+13
source

Source: https://habr.com/ru/post/969406/


All Articles