BiPredicate<T, U>
is a functional interface (a SAM type) with the signature boolean test(T t, U u)
. When a method accepts a SAM-typed argument, you can pass an explicit implementation of the class, a lambda expression, or a method ref.
If you don’t need to pass your function around and invoke it from other places, stay with a plain old function. But if you need another method to receive a predicate, you will need to encode this into a type.
Let’s quickly look at some examples:
class MyClass {
public static boolean stringEquals(final String s1, final String s2) {
return s1.equals(s2);
}
}
final BiPredicate<String, String> lambda = (a, b) -> MyClass.stringEquals(a, b);
final BiPredicate<String, String> lambda2 = (a, b) -> a.equals(b);
final BiPredicate<String, String> ref = MyClass::stringEquals;
final BiPredicate<String, String> ref2 = String::equals;
final BiPredicate<String, String> anonymous = new BiPredicate<>() {
@Override boolean test(final String x, final String y) {
return MyClass.stringEquals(x, y);
}
};
final BiPredicate<String, String> anonymous2 = new BiPredicate<>() {
@Override boolean test(final String x, final String y) {
return x.equals(y);
}
};
final boolean same = lambda.test("yes", "yes");
final boolean same2 = lambda2.test("no", "no");
final boolean different = ref.test("yes", "no");
final boolean different2 = ref2.test("yes", "no");
final boolean equal = anonymous.test("maybe", "maybe");
final boolean equal2 = anonymous2.test("maybe", "maybe");
Say you are writing a component that needs to compare strings, but you want users of your component to decide on how strings should be compared (String#equals
, Objects#equals
, String#equalsIgnoreCase
). You could define your method as follows:
class MyComponent {
public boolean compare(final String s1, final String s2, final BiPredicate<String, String> pred) {
return pred.test(s1, s2);
}
}
final boolean truthy = component.compare("yes", "YES", String::equalsIgnoreCase);
final boolean falsy = component.compare("yes", "YES", String::equals);
// or something completely different:
final boolean result = component.compare("yes", "maybe", (a, b) -> a.length()*2 == b.length()+1);