4

In Guava, we can do stuff like

Predicate<String> isEmpty = Predicates.compose(String::length, Integer.valueOf(0)::equals); // contrived, I know

Can we do something similar in Java 8? For example

Predicate<Integer> isZero = Integer.valueOf(0)::equals;
Predicate<String> isEmpty = isZero.compose(String::length);

or a library function that achives the same?

Note that I'm not asking about how to do this myself (s -> isZero.test(s.length) works fine) or why this doesn't work in line (Lambda types are inferred and all that)

Jorn
  • 20,612
  • 18
  • 79
  • 126
  • Are you looking for something similar described here -> http://howtodoinjava.com/java-8/how-to-use-predicate-in-java-8/ – Rakesh Dec 06 '16 at 09:43
  • There's nothing built-in similar to `Predicates.compose(...)`. – Spotted Dec 06 '16 at 10:43
  • I think you are looking for functions as first class citizens like in Scala: e.g. `val isZero = (x: Int) => x==0` `val size = (s:String) => s.length` `val isEmpty = size andThen isZero`, which is function composition in the mathematical sense ` f o g (x)` – maasg Dec 07 '16 at 13:07

1 Answers1

3

You can easily write a compose method and use that in multiple places:

import java.util.function.*;

public class Test {
    public static void main(String[] args) {
        Integer zero = 0;
        Predicate<Integer> isZero = zero::equals;
        Predicate<String> isEmpty = compose(String::length, isZero);

        System.out.println(isEmpty.test("")); // true
        System.out.println(isEmpty.test("x")); // false
    }

    // Composition of a function with a predicate
    public static <T, S> Predicate<T> compose(Function<T, S> first, Predicate<S> second) {
        return input -> second.test(first.apply(input));
    }
}

(I removed references to Integer.ZERO as that doesn't exist...)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    You don't need to define `compose` for `Function`. It already exists in the `Function` interface - `default Function compose(Function super V, ? extends T> before)` – Eran Dec 06 '16 at 09:51
  • 1
    @Eran: Ah, nice, I hadn't seen that :) – Jon Skeet Dec 06 '16 at 09:55
  • 1
    @Jorn: Well you gave an example which *hard-coded* that - whereas I've provided the *reusable* form. It's not clear you knew how to build that - or why you'd care whether the reusable form were in the Java 8 standard library or your own library. – Jon Skeet Dec 06 '16 at 10:02
  • 4
    @Jorn: as written [here](http://stackoverflow.com/a/33308391/2711488), you *can* use `f.andThen(Predicate.isEqual(value)::test)::apply` if using existing features is all that matters to you. Otherwise, there is nothing wrong with a lambda expression, especially, as it is shorter and more efficient than the supposed factory method. But note that `Predicate isZero = Predicate.isEqual(0);` *does* exist. – Holger Dec 06 '16 at 10:56