Examples of lambda expressions used with forEach(), removeIf(), replaceAll() and sort() functions

In this tutorial I will cover the use of lambda expressions with the Collection’s functions forEach(), removeIf(), replaceAll() and sort() . The Lambda Expressions can replace a type of Functional Interface.

There are several Functional interfaces included in Java 8, located in the package java.util.function. The choice of any of these FIs depends on the situation. For example, in our tutorial, each of the mentioned functions takes a specific type type of Functional Interface (BiConsumer, Predicate, etc) .

forEach

Use case with java.util.Map

When used with a Map, the forEach() function takes in parameter an object of type BiConsumer, which is a specialization of the Consumer functional interface.

As a Map element is defined by a key and a value, the BiConsumer FI represents an operation that accepts two input arguments and returns no result.

So, for this example I will create a map that contains  the names of some of Real Madrid soccer team players as values, and their numbers as keys. Then, I will iterate through the players using the forEach function and display each one prefixed by his number.

Map<Integer, String> players = new HashMap<Integer, String>();
players.put(2, "Dani Carvajal");
players.put(19, "Achraf Hakimi");
players.put(4, "Sergio Ramos");
players.put(12, "Marcelo");
players.put(8, "Toni Kroos");
players.put(7, "Christano Ronaldo");

Now I will call the forEach() function from the players Map. I will create a functional interface of type BiConsumer to hold the lambda expression that will print each player.

BiConsumer<Integer, String> consumer = (k,v)-> System.out.println(k + " : "+ v);
players.forEach(consumer);

This can be simplified to only one line like the following :

players.forEach((k,v)-> System.out.println(k + " : "+ v));

The execution will print the following list:

2 : Dani Carvajal
19 : Achraf Hakimi
4 : Sergio Ramos
7 : Christano Ronaldo
8 : Toni Kroos
12 : Marcelo

 

Use case with java.util.List

For this example, I will use the same list of players but without the keys (the numbers) as I will be using a List instead of a Map.

When used with a List, the method forEach() takes an object of type Consumer as parameter.

List<String> players = new ArrayList<String>();
players.add("Dani Carvajal");
players.add("Achraf Hakimi");
players.add("Sergio Ramos");
players.add("Marcelo");
players.add("Toni Kroos");
players.add("Christano Ronaldo");

Then I will create my lambda expression of type Consumer that will take a parameter of type String and print it on the Console. The Consumer object ( or the lambda expression) will be passed as parameter to the forEach() function in order to display the player names.

Consumer<String> consumer = (player)-> System.out.println(player);
players.forEach(consumer);

This will print the following :

Dani Carvajal
Achraf Hakimi
Sergio Ramos
Marcelo
Toni Kroos
Christano Ronaldo

Of course, I could use only one line to simplify the code:

players.forEach((player)-> System.out.println(player));

 

removeIf

The remove if function takes an object of type java.util.function.Predicate as parameter.

A Predicate is a Functional Interface that represents a boolean-valued function of one argument. It means that the Lambda Expression I will create will take a parameter and return a boolean.

To show the use of the removeIf() function, I will create the same list but I will do an intentional mistake : I will add Messi the list of Real Madrid players, so I will use the removeIf function to delete the players with a name equal to Messi, then I will print the List.

// create the list
List<String> players = new ArrayList<String>();
players.add("Dani Carvajal");
players.add("Achraf Hakimi");
players.add("Sergio Ramos");
players.add("Marcelo");
players.add("Toni Kroos");
players.add("Christano Ronaldo");
players.add("Messi");

// create the lambda expression of type Predicate
Predicate<String> predicate = player -> player.equals("Messi");
players.removeIf(predicate);

// display the players
players.forEach((player)-> System.out.println(player));

The result of execution will be a list without Messi !

Dani Carvajal
Achraf Hakimi
Sergio Ramos
Marcelo
Toni Kroos
Christano Ronaldo

replaceAll

The replaceAll() function takes as parameter a Functional Interface of type UnaryOperator when used with a List. A UnaryOperator represents an operation on a single operand that produces a result of the same type as its operand.

In this example, and for a reason I don’t know, I will replace all the name of Christiano Ronaldo by ********* . Practicality, My Lambda Expression will take a parameter of type String  and return a value of the same time but after the replacement by ******** is done.

// create the list
List<String> players = new ArrayList<String>();
players.add("Dani Carvajal");
players.add("Achraf Hakimi");
players.add("Sergio Ramos");
players.add("Marcelo");
players.add("Toni Kroos");
players.add("Christano Ronaldo");

// create the lambda expression
UnaryOperator<String> unaryOperator = 
  s->{
   if(s.equals("Christano Ronaldo")){
    return "******";
   }else{
    return s;
   }
  };

// do the replacement 
players.replaceAll(unaryOperator);

// display the list
players.forEach((player)-> System.out.println(player));

The result will be as follow :

Dani Carvajal
Achraf Hakimi
Sergio Ramos
Marcelo
Toni Kroos
******

sort

The Collection’s sort() method takes two objects as parameter :

  1. The list being sorted;
  2. A Functional Interface of type Comparable (say an Interface of type Comparable for java 7 and bellow).

In previous versions of Java, we had to implement the Interface Comparable and override the compare() method in order to implement the way in which we want the comparison to be done.

In Java 8 however, All we have to do is to pass a Lambda Expression as second parameter, defining how the comparison is done.

in this example I will sort a list of players based on their score.

I will first create a Player class .

class Player {
   
   private String name;
   private Integer score;

   // Constructor with parameters
   public Player(String name, int score){
    this.name = name;
    this.score = score;
   }
   
   public String getName() {
    return name;
   }
   
   public void setName(String name) {
    this.name = name;
   }
   
   public Integer getScore() {
    return score;
   }
   
   public void setScore(Integer score) {
    this.score = score;
   }
   
   @Override
   public String toString() {
    return "[name : "+this.name+", score : "+this.score+"]";
   }
   
}

Then I will create a list of players with their scores, and passing  two parameters to the sort( ) function :

  1. The list to sort;
  2. a Lambda Expression determining how the comparison is done.
// Create a list of players
List<Player> playerList = new ArrayList<Player>();

// add some players, and their scores
playerList.add(new Player("Messi",500));
playerList.add(new Player("Ronaldo",750));
playerList.add(new Player("Roberto",900));
playerList.add(new Player("Albert",450));
playerList.add(new Player("Michel",750));
playerList.add(new Player("Mario",750));

// 1-Define how the sorting will be done in the Lambda Expression (Second parameter)
// 2-sort
Collections.sort(playerList, (p1, p2) -> p1.getScore().compareTo(p2.getScore()) );

// display the sorted list of players (ascendent order)
System.out.println(playerList);

The result of the execution will be as follow :

[[name : Albert, score : 450], [name : Messi, score : 500], [name : Ronaldo, score : 750], [name : Michel, score : 750], [name : Mario, score : 750], [name : Roberto, score : 900]]