Sitemap
Full Stack Developer

Full Stack Developer

This blog is curated just for you, if you are a Developer planning to appear for interviews OR looking out for new & interesting things happening in Java Space.

Functional Interfaces Review — BiPredicate

3 min readJul 6, 2024

--

Press enter or click to view image in full size
Photo by Megan Bucknall on Unsplash

The BiPredicate interface in Java is similar to the Predicate interface, but it takes two input arguments instead of one. It is a part of the java.util.function package and represents a predicate (boolean-valued function) of two arguments. Here’s everything you need to know about the BiPredicate interface, along with examples:

Definition

The BiPredicate interface is defined as follows:

@FunctionalInterface
public interface BiPredicate<T, U> {
boolean test(T t, U u);

default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) {
Objects.requireNonNull(other);
return (t, u) -> test(t, u) && other.test(t, u);
}
default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other) {
Objects.requireNonNull(other);
return (t, u) -> test(t, u) || other.test(t, u);
}
default BiPredicate<T, U> negate() {
return (t, u) -> !test(t, u);
}
}

Methods

  1. test(T t, U u): This is the single abstract method of the BiPredicate interface. It evaluates the predicate on the given arguments and returns a boolean value.
  2. and(BiPredicate<? super T, ? super U> other): This is a default method that returns a composed predicate that represents a short-circuiting logical AND of this predicate and another.
  3. or(BiPredicate<? super T, ? super U> other): This is a default method that returns a composed predicate that represents a short-circuiting logical OR of this predicate and another.
  4. negate(): This is a default method that returns a predicate that represents the logical negation of this predicate.

Key Points

  • Since BiPredicate is a functional interface, it can be implemented using lambda expressions or method references.
  • BiPredicate is often used for filtering or matching pairs of objects based on a condition.

Usage Examples

Basic Example

Here’s a simple example of how to use the BiPredicate interface:

Get Full Stack Developer’s stories in your inbox

Join Medium for free to get updates from this writer.

import java.util.function.BiPredicate;

public class BiPredicateExample {
public static void main(String[] args) {
// Define a BiPredicate that checks if the sum of two numbers is greater than 10
BiPredicate<Integer, Integer> sumGreaterThanTen = (a, b) -> (a + b) > 10;
// Use the BiPredicate
System.out.println(sumGreaterThanTen.test(5, 7)); // true
System.out.println(sumGreaterThanTen.test(3, 4)); // false
}
}

Chaining BiPredicates

You can chain multiple BiPredicate instances using the and, or, and negate methods:

import java.util.function.BiPredicate;

public class BiPredicateChainingExample {
public static void main(String[] args) {
// Define two BiPredicates
BiPredicate<String, String> isEqual = String::equals;
BiPredicate<String, String> isNotNull = (s1, s2) -> s1 != null && s2 != null;
// Chain the BiPredicates
BiPredicate<String, String> combinedPredicate = isNotNull.and(isEqual);
// Use the combined BiPredicate
System.out.println(combinedPredicate.test("Hello", "Hello")); // true
System.out.println(combinedPredicate.test(null, "Hello")); // false
}
}

Using Method References

You can also use method references with BiPredicate:

import java.util.function.BiPredicate;
import java.util.Map;

public class MethodReferenceExample {
public static void main(String[] args) {
// Define a BiPredicate using a method reference
BiPredicate<Map<String, String>, String> containsKey = Map::containsKey;
// Use the BiPredicate with a Map
Map<String, String> map = Map.of("Alice", "Engineer", "Bob", "Manager");
System.out.println(containsKey.test(map, "Alice")); // true
System.out.println(containsKey.test(map, "Charlie")); // false
}
}

Using BiPredicate with Collections

You can use BiPredicate to filter pairs of elements in collections:

import java.util.List;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

public class ListBiPredicateExample {

public static void main(String[] args) {
List<String> words = List.of("Apple", "Banana", "Cherry", "Date");
List<Integer> lengths = List.of(5, 6, 6, 4);
// Define a BiPredicate that checks if a word has the specified length
BiPredicate<String, Integer> hasLength = (word, length) -> word.length() == length;
// Use the BiPredicate to filter the lists
List<String> filteredWords = words.stream()
.filter(word -> lengths.stream().anyMatch(length -> hasLength.test(word, length)))
.collect(Collectors.toList());
System.out.println(filteredWords); // [Apple, Banana, Date]
}
}

Practical Use Cases

  1. Filtering Collections: BiPredicate can be used to filter elements in collections based on conditions involving two arguments.
  2. Conditional Checks: Used for conditional checks that involve two parameters.
  3. Validation: Can be used for validating pairs of inputs.
  4. Event Handling: Used to handle events that involve two pieces of data.

Summary

The BiPredicate interface is a functional interface in Java that represents a condition or a boolean-valued function of two arguments. It is useful for filtering and matching purposes involving pairs of objects, and it can be implemented using lambda expressions and method references. The interface also provides methods for logical operations (and, or, negate). BiPredicate is a versatile tool in functional programming, particularly in contexts where two inputs need to be evaluated together.

--

--