Understanding Java’s Consumer, Supplier and Predicate

February 12, 2021 | java |

Functional programming in Java in a better way.

Functional interfaces provide target types for lambda expressions and method references. Each functional interface has a single abstract method, called the functional method for that functional interface, to which the lambda expression’s parameter and return types are matched or adapted.

Interface Consumer<T>

Represents an operation that accepts a single input argument and returns no result. Unlike most other functional interfaces, Consumer is expected to operate via side-effects.

void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after);

The accept method is the Single Abstract Method (SAM) which accepts a single argument of type T.

Whereas, the other one andThen is a default method used for composition.

List<String> cities = Arrays.asList("Sydney", "Dhaka", "New York", "London");

Consumer<List<String>> upperCaseConsumer = list -> {
    for(int i=0; i< list.size(); i++){
        list.set(i, list.get(i).toUpperCase());
    }
};

Consumer<List<String>> printConsumer = list -> list.forEach(System.out::println);

upperCaseConsumer.andThen(printConsumer).accept(cities);

Consumer interface has specific implementation types for integer, double and long types

IntConsumer void accept(int x);
DoubleConsumer void accept(double x);
LongConsumer void accept(long x);

Interface Supplier<T>

Represents a supplier of results.

There is no requirement that a new or distinct result be returned each time the supplier is invoked.

This is a functional interface whose functional method is get().

T get()
Supplier<String> supplier = () -> {
    String res = "Success";
    // Do something and return a result.
    return res;
};

System.out.println(supplier.get());

Supplier interface has specific implementation types for boolean, integer, double and long types

Booleansupplier boolean getAsBoolean();
DoubleSupplier double getAsDouble();
IntSupplier int getAsInt()
LongSupplier long getAsLong();

public interface Predicate<T>

Represents a predicate (boolean-valued function) of one argument.

This is a functional interface whose functional method is test(Object).

boolean	test(T t);

default Predicate<T> and(Predicate<? super T> other)
static <T> Predicate<T>	isEqual(Object targetRef);
default Predicate<T> negate();
static <T> Predicate<T>	not(Predicate<? super T> target);
default Predicate<T> or(Predicate<? super T> other)

Example

Code

List<Integer> numbers      = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> moreNumbers1 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> moreNumbers2 = Arrays.asList(11, 12, 13, 14, 15, 16, 17, 18, 19, 20);

Predicate<Integer> p1 = num -> num < 5;
Predicate<Integer> p2 = n -> n > 3;
Predicate<Integer> p3 = n -> n < 7;

// test()
System.out.println("******* TEST() *********");
System.out.println(p1.test(10) ? "10 is smaller than 5" : "10 is bigger than 5");

// negate()
System.out.println("******* NEGATE() *********");
numbers.stream().filter(p1.negate()).forEach(System.out::println);

// not()
System.out.println("******* NOT() *********");
System.out.println(Predicate.not(p1).test(10));
System.out.println(Predicate.not(p1).test(2));

// and()
System.out.println("******* AND() *********");
numbers.stream().filter(p2.and(p3)).forEach(System.out::println);

// isEqual()
System.out.println("******* ISEQUAL() *********");
Predicate<Object> p4 = Predicate.isEqual(numbers);
System.out.println(p4.test(moreNumbers1));
System.out.println(p4.test(moreNumbers2));

// or()
System.out.println("******* OR() *********");
numbers.stream().filter(p2.or(p3)).forEach(System.out::println);

Output

******* TEST() *********
10 is bigger than 5

******* NEGATE() *********
5
6
7
8
9
10

******* NOT() *********
true
false

******* AND() *********
4
5
6

******* ISEQUAL() *********
true
false

******* OR() *********
1
2
3
4
5
6
7
8
9
10
Edit this post on GitHub

Leia também