4

In Java 8, the Comparator class has this really nifty static method that composes a Function to a Comparator by using the the result of the Function as the input for the Comparator.

What I would like to do, is be able to compose Function objects with other types like Predicate, in order to make my code more readable, and to make my functional operations more powerful.

For example, say there is a Set<Person> where Person has a public String getName() method. I want to be able to filter out the Person objects that don't have a name. Ideally, the syntax would look like this:

people.removeIf(Predicates.andThenTest(Person::getName, String::isEmpty));

Are there any built-in methods that can compose a Function with something like a Predicate? I'm aware of Function#andThen(Function), but that is only useful for combining functions with other functions, and sadly, Predicate doesn't extend Function<T, Boolean>.

P.S. I'm also aware that I could use a lambda like p -> p.getName().isEmpty(), but I would like for a way to compose pre-existing Predicate objects with a Function.

4castle
  • 32,613
  • 11
  • 69
  • 106
  • Given the responses to [How to negate a method reference predicate](http://stackoverflow.com/questions/21488056/how-to-negate-a-method-reference-predicate?rq=1), I'm thinking my question is probably in a family of questions which wish `Predicate` was implemented better. Hopefully it will be improved in the future :) – 4castle Jul 08 '16 at 16:16
  • Given how long lambda has been developed before made it to jdk eventually, I am thinking whether the reason of `Predicate` and `Function` being in the language [is the same as in .NET](http://stackoverflow.com/a/665513/1026104) – jan.supol Jul 08 '16 at 16:19
  • 2
    There are so many possible functional combinations that it is pointless to ask why a particular combination has been provided and another hasn’t. All you need to now is that there is none and you can create your own, which has no drawbacks compared to a hypothetical JRE provided solution. – Holger Jul 08 '16 at 16:41
  • @Holger I agree. Part of my reason for bringing this up is that I see that this is a very common operation in SO questions which usually can't be solved without a lambda. I'm one of those guys who prefers not to use a lambda where possible (kind of like striving for point-free notation in Haskell, I like my Streams free of lambdas where possible) – 4castle Jul 08 '16 at 16:46
  • 4
    Well, if you want to avoid the `t -> pred.test(func.apply(t))` lambda expression at all costs, you can write `func.andThen(pred::test)::apply` instead. But really, there are places, where you should accept a lambda expression. After all, that’s what the JRE provided factory would use internally too. – Holger Jul 08 '16 at 16:50
  • I've moved my workaround method to the answers, so that the Q&A format still fits. Future readers may find it helpful to see the check mark so that they don't have to read all of the comments. – 4castle Jul 11 '16 at 16:00

2 Answers2

0

You can make cast a Predicate as a Function like this:

Predicate<String> p = String::isEmpty;
Function<String, Boolean> g = p::test; // predicate to function
Function<Boolean, String> f = Object::toString;
f.compose(g); // or g.andThen(f);
cdelmas
  • 840
  • 8
  • 15
  • Sweet! But then for me to use it on a function that takes a predicate, I need to cast that composed `Function` back to a `Predicate`. @Holger used `::apply` to do that. It's fairly awkward to read, which makes me hesitant, but it certainly can work in a pinch! I think I'll stick with my static method for now. – 4castle Jul 11 '16 at 15:40
0

There isn't a value extractor method for predicates built into Java 8, but the next best solution is to implement it yourself:

public class Predicates {
    public static <T,R> Predicate<T> andThenTest(
            Function<T,R> func, Predicate<R> pred) {
        return t -> pred.test(func.apply(t));
    }
}

Thanks to @Holger, that could also be:

return func.andThen(pred::test)::apply;
4castle
  • 32,613
  • 11
  • 69
  • 106