Java 8 – Lambda Predicates

Predicate is a functional interface in java 8. It’s used to hold the lambda expression and takes a value or an object and return a boolean value.

This is very handy if you want to do any validation or filtering anythig.

Refer the below example to know how to use the Predicate for validating the number whether it’s even or not and some more operations.


import java.util.function.Predicate;

public class PredicateMain {

    public static void main(String[] args) {
        // Validate whether the number is even or not.
        System.out.println("Predicates.isEven(2)::" + Predicates.isEven().test(2));
        // Validate whether the number is odd or not.
        System.out.println("Predicates.isOdd(3) ::" + Predicates.isOdd().test(3));
        // Validate whether the number is even and also greater than 100
        System.out.println("Predicates.isEven().and(Predicates.isGreaterThan100(100)) ::"
                + Predicates.isEven().and(Predicates.isGreaterThan100()).test(100));
        // Validate whether the number is even and also greater than 100
        System.out.println("Predicates.isEven().and(Predicates.isGreaterThan100(102)) ::"
                + Predicates.isEven().and(Predicates.isGreaterThan100()).test(102));
        // Validate whether the number is even or greater than 100
        System.out.println("Predicates.isEven().or(Predicates.isGreaterThan100(101)) ::"
                + Predicates.isEven().or(Predicates.isGreaterThan100()).test(101));
        // Validate whether the number is even and negate the result.
        System.out.println("Predicates.isEven().negate(11) ::" + Predicates.isEven().negate().test(11));
    }

    static class Predicates {

        public static Predicate isEven() {
            return number -> number % 2 == 0;
        }

        public static Predicate isOdd() {
            return number -> number % 2 != 0;
        }

        public static Predicate isGreaterThan100() {
            return number -> number > 100;
        }
    }
}


Output:



Predicates.isEven(2)::true
Predicates.isOdd(3) ::true
Predicates.isEven().and(Predicates.isGreaterThan100(100)) ::false
Predicates.isEven().and(Predicates.isGreaterThan100(102)) ::true
Predicates.isEven().or(Predicates.isGreaterThan100(101)) ::true
Predicates.isEven().negate(11) ::true


Refer the below example to know how we can use this for filtering


import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateCollections {

    public static void main(String[] args) {

        List users = Arrays.asList(new User("Bob", 51, 170), new User("john", 52, 80), new User("paul", 45 ,120), new User("alex", 46, 150), new User("scott", 56, 150));

        //All the users whose age are above 50
        List above50Users = filter(users, isAgeAbove50());
        System.out.println("The above 50 age users \n" + above50Users);

        //All the users whose age are below 50
        List below50Users = filter(users, isAgeBelow50());
        System.out.println("The below 50 age users \n"+ below50Users);

        //We can also use the negate expression. Lets see how we can do that
        above50Users = filter(users, isAgeBelow50().negate());
        System.out.println("The above 50 age users \n" + above50Users);

        below50Users = filter(users, isAgeAbove50().negate());
        System.out.println("The below 50 age users \n"+ below50Users);

        //Users whose age is above 50 and weight is more than 100
        List above50AndExcessWeightUsers = filter(users, isAgeAbove50().and(isWeightGtThan100()));
        System.out.println("The above 50 and excess weight users \n"+ above50AndExcessWeightUsers);
    }

    public static Predicate isAgeAbove50() {
        return user -> user.age > 50;
    }

    public static Predicate isAgeBelow50() {
        return user -> user.age < 50;
    }
    public static Predicate isWeightGtThan100() {
        return user -> user.weight > 100;
    }

    public static List filter(List users, Predicate p) {
        return users.stream().filter(p::test).collect(Collectors.toList());
    }

    static class User {

        String name;
        int age;
        int weight;

        User(String name, int age, int weight) {
            this.name = name;
            this.age = age;
            this.weight = weight;
        }

        @Override
        public String toString() {
            return "name:"+name +" age:"+age + " weight:"+weight;
        }
    }
}

Output:


The above 50 age users 
[name:Bob age:51 weight:170, name:john age:52 weight:80, name:scott age:56 weight:150]
The below 50 age users 
[name:paul age:45 weight:120, name:alex age:46 weight:150]
The above 50 age users 
[name:Bob age:51 weight:170, name:john age:52 weight:80, name:scott age:56 weight:150]
The below 50 age users 
[name:paul age:45 weight:120, name:alex age:46 weight:150]
The above 50 and excess weight users 
[name:Bob age:51 weight:170, name:scott age:56 weight:150]


Java 8: Create LinkedHashMap with Collectors.toMap

In this article, I will show you how to create a LinkdHashMap with Collectors.toMap() method.

Assume that you have a LinkedHashMap with the key as a string and the value as an Integer. Now you want to iterate this map and modify the value of each key and then create an another map to hold that value.

Refer the below code to know how to do that.



import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {

        Map map1 = new LinkedHashMap();

        map1.put("key1", 1);
        map1.put("key2", 2);
        map1.put("key3", 3);

        System.out.println(map1);

        Map map2 = map1.keySet()
                .stream()
                .collect(Collectors.toMap(key -> key,
                        key -> (map1.get(key) + 10),
                        (e1, e2) -> e1,
                        LinkedHashMap::new));

        System.out.println(map2);
    }
}


By default, the Collectors.toMap function creates a HashMap but we can override it by specifying the mapSupplier argument. The corresponding function from Collectors class which should be used in this case.


    public static <T, K, U, M extends Map<K, U>>
    Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper,
                                BinaryOperator<U> mergeFunction,
                                Supplier<M> mapSupplier) 

So in my code,I am passing the key, updated value, merge function(consider the first key if there is a duplicate key), finally the LinkedHashMap to the Collectors.toMap() function.

The output will be like this,


 map1{key1=1, key2=2, key3=3}
 map2{key1=11, key2=12, key3=13}