Predicate interface in Java

A Predicate interface represents a boolean-valued-function of an argument. This is mainly used to filter data from a Java stream. The filter method of a stream accepts a predicate to filter the data and return a new stream satisfying the predicate. 
A predicate has a test() method which accepts an argument and returns a boolean value.
```
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Main {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("a", "b", "ab", "d", "ae");
        Predicate<String> nameStartsWithS = str -> str.startsWith("a");
        names.stream().filter(nameStartsWithS).forEach(System.out::println);
    }
}
```
Predicate also provides a few default and static method for composition and other purposes:
```
default Predicate<T> and(Predicate<? super T> other);
default Predicate<T> or(Predicate<? super T> other);
static <T> Predicate<T> isEquals(Object targetRef);
default Predicate<T> negate();
```
Following example demonstrates to use and() method to compose predicates with multiple predicates.
```
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Main {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("a", "b", "ab", "d", "aeb");
        Predicate<String> startPredicate = str -> {return str.startsWith("a"); };
        Predicate<String> endPredicate = (str) -> str.endsWith("b");
        names.stream().filter(startPredicate.and(endPredicate)).forEach(System.out::println);
        // ab
        // aeb
    }
}
```
BiPredicate is a functional interface, which accepts two arguments and returns a boolean, basically this BiPredicate is same with the Predicate, instead, it takes 2 arguments for the test.