Java @ Desk: Lambda | Java at your desk

Default method in interface in Java

Default method in interface in Java

Default methods have been introduced in Java 8 in order to extend the feature providing an default implementation across all implementation classes.
The main intention of introducing default method is to have a method with implementation in an existing interface without affecting implementation classes. Introduing a new method declaration in existing interface force the change in all implementation classes. The default method comes with an implementation thus making it all optional for the classes to provide the implementation.
Still, the class can override the default implementation of the default method of interface.
So, interface in Java can define a method. An implementation class may or may not override the default implementation.

package com.learning;

public interface DefaultInterface {

 default public void defaultInterfaceDefinedMethod() {
  System.out.println("Default Interface method is called");
 }
}


package com.learning;

public class DefaultInterfaceImpl implements DefaultInterface {

}


package com.learning;

public class DefaultInterfaceMain {

 public static void main(String args[]) {

  DefaultInterface defaultInterface = new DefaultInterfaceImpl();
  defaultInterface.defaultInterfaceDefinedMethod();
 }

}



For Java 8, the JDK collections have been extended and forEach method is added to the entire collection (which work in conjunction with lambdas). The same mechanism has been used to add Stream in JDK interface without breaking the implementing classes.

What about Multiple Inheritance?
public interface DefaultInterface {

 default public void defaultInterfaceDefinedMethod() {
  System.out.println("Default Interface method is called");
 }
}

public interface DefaultInterfaceTwo {

 default public void defaultInterfaceDefinedMethod() {
  System.out.println("Default Interface Two method is called");
 }
}

public class DefaultInterfaceImpl implements DefaultInterface, DefaultInterfaceTwo {

}


This generates compilation error since the implementation class finds the same default method in both the interfaces. In order to fix this class, we need to provide default method implementation in the class itself i.e. it now becomes mandatory for the class to override the default implementation as shown below
public class DefaultInterfaceImpl implements DefaultInterface, DefaultInterfaceTwo {

 @Override
 public void defaultInterfaceDefinedMethod() {
 }

}


Further, if we want to invoke default implementation provided by any of super interface rather than our own implementation, we can do so as follows,
package com.learning;

public class DefaultInterfaceImpl implements DefaultInterface, DefaultInterfaceTwo {

 @Override
 public void defaultInterfaceDefinedMethod() {
  DefaultInterface.super.defaultInterfaceDefinedMethod();
 }

}


How to iterate a Map of objects using forEach and Lambda in Java 8

How to iterate a Map of objects using forEach and Lambda in Java 8

Prior to Java 8, iterating over a map of object was done using normal Map.Entry interface. In Java 8, forEach method of a Map interface is used to iterate over the map of objects.

forEach method takes 2 parameters as key and value.

Below is the example of the same. Here is a Person class with name, age & address property. The main program creates 3 objects of Person class and iterate over the map using forEach method and prints the key and age of each person.

Person.java
package com.pojo;

public class Person {

 private String id;

 private String name;

 private String address;

 private int age;

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getAddress() {
  return address;
 }

 public void setAddress(String address) {
  this.address = address;
 }
}


IterateMap.java
package com.lambda;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.pojo.Person;

public class IterateMap {

 public static void main(String args[]) {

  Map<String, Person> personMap = new HashMap<>();

  Person person = new Person();
  person.setAge(20);
  personMap.put("FirstPerson", person);

  Person personOne = new Person();
  personOne.setAge(25);
  personMap.put("SecondPerson", personOne);

  Person personTwo = new Person();
  personTwo.setAge(32);
  personMap.put("ThirdPerson", personTwo);

  Person personThree = new Person();
  personThree.setAge(14);
  personMap.put("FourthPerson", personThree);

  personMap.forEach((key, personValue) -> {
   System.out.println("Key : " + key + ", Person Age : " + personValue.getAge());
  });
 }
}


How to iterate a List of objects using forEach and Lambda in Java 8

How to iterate a List of objects using forEach and Lambda in Java 8

Prior to Java 8, iterating over a list of object was done using normal for loop or advanced for loop in case of Generics collection. In Java 8, forEach method of a List interface is used to iterate over the list of objects.

forEach method takes a single parameter that is actual object type of which the collection or list object is made of.

Below is the example of the same. Here is a Person class with name, age & address property. The main program creates 3 objects of Person class and iterate over the list using forEach method and prints the age of each person.

Person.java
package com.pojo;

public class Person {

 private String id;

 private String name;

 private String address;

 private int age;

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getAddress() {
  return address;
 }

 public void setAddress(String address) {
  this.address = address;
 }
}


IterateList.java
package com.lambda;

import java.util.ArrayList;
import java.util.List;

import com.pojo.Person;

public class IterateList {

 public static void main(String args[]) {

  List<Person> persons = new ArrayList<>();

  Person person = new Person();
  person.setAge(20);
  persons.add(person);

  Person personOne = new Person();
  personOne.setAge(25);
  persons.add(personOne);

  Person personTwo = new Person();
  personTwo.setAge(32);
  persons.add(personTwo);

  Person personThree = new Person();
  personThree.setAge(14);
  persons.add(personThree);

  persons.forEach(personObject -> {
   System.out.println("Person Name - " + personObject.getAge());
  });
 }
}


Filter Java Collection using Java 8 Lambda & Stream Filter

Filter Java Collection using Java 8 Lambda & Stream Filter

In this post, we will learn how to filter a list based on certain criteria. If we have a list of objects and we need a filtered list based on certain condition, then prior to Java 8 we need to iterate through the list and apply if conditions and get each object to add in the temporary list.

In Java 8, stream & filter operations using Lambda expressions helps to get the filtered list in a single statement itself.

Filter a stream of data for a given criteria and perform collect operations to get the collection of objects for the given criteria.

Below is the Java example for the same. There is a list of Person object and filter is applied to get all the persons where age of a person is greated than 18.

package com.pojo;

public class Person {

 private String id;

 private String name;

 private String address;

 private int age;

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getAddress() {
  return address;
 }

 public void setAddress(String address) {
  this.address = address;
 }
}


package com.lambda;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.pojo.Person;

public class FilterListLambda {

 public static void main(String args[]) {

  List<Person> persons = new ArrayList<>();

  Person person = new Person();
  person.setAge(20);
  persons.add(person);

  Person personOne = new Person();
  personOne.setAge(25);
  persons.add(personOne);

  Person personTwo = new Person();
  personTwo.setAge(32);
  persons.add(personTwo);

  Person personThree = new Person();
  personThree.setAge(14);
  persons.add(personThree);

  // Find all persons where age greater than 18 using traditional For Loop

  List<Person> personsAgeGreaterThan18 = new ArrayList<>();

  for (Person tempPerson : persons) {
   if (tempPerson.getAge() > 18) {
    personsAgeGreaterThan18.add(tempPerson);
   }
  }

  // Using Java 8 Lambda & Streams

  personsAgeGreaterThan18 = persons.stream().filter(p -> p.getAge() > 18).collect(Collectors.toList());
 }
}


How to print a list or a collection using Lambda Expression in Java 8

How to print a list or a collection using Lambda Expression in Java 8

In this example, we will learn how to print a list using Lambda expression in Java 8. Traditional methods were using the normal for loop and use the System.out.println method to print the content of a collection.

There are 2 ways to print a list using Lambda expression -
1) Using lambda expression and functional operations
2) Using double colon operator in Java 8

Both these ways reduce the code to a single statement which is more readable and easy to maintain.

Below is the short example to demonstrate both the examples.
package com.lambda;

import java.util.ArrayList;
import java.util.List;

public class ForLoopPrint {

 public static void main(String args[]) {

  List<String> persons = new ArrayList<>();

  persons.add("John");
  persons.add("Adam");
  persons.add("Peter");
  persons.add("James");

  System.out.println("Using Old Loop");
  for (String person : persons) {
   System.out.print(person + "; ");
  }
  System.out.println("\n");

  System.out.println("Using lambda expression and functional operations");
  persons.forEach((person) -> System.out.print(person + "; "));

  System.out.println("\n");
  System.out.println("Using double colon operator in Java 8");
  persons.forEach(System.out::println);
 }
}


Here is the output -
Using Old Loop
John; Adam; Peter; James; 

Using lambda expression and functional operations
John; Adam; Peter; James; 

Using double colon operator in Java 8
John
Adam
Peter
James

Sorting a List using Lambda Expression in Java 8

Sorting a List using Lambda Expression in Java 8

In this post, we will learn how to sort a list using Lambda Expression in Java 8. In Java 6 or 7, Java pojo object must implements Comparator interface or Comparable interface to sort a collection of objects. The implementation need to be provided in compareTo method to sort a list based on particular property of a class.

In Java 8, the code has been reduced to just a single line. One can use the below 3 implementations:
1) sort method of List interface
2) sort method of Collections class
3) sort using stream() method of List interface

In 3rd strategy, the underlying list does not get sorted. So, either you must create a new object and assign the sorted list or assign the sorted list to the existing list object.
In both the implementations, the sorting logic goes as a Lambda expression.

Consider a Person class below in which sorting logic needs to be implemented on name of the person.
package com.pojo;

public class Person {

 private String id;

 private String name;

 private String address;

 public Person(String id, String name, String address) {
  super();
  this.id = id;
  this.name = name;
  this.address = address;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getAddress() {
  return address;
 }

 public void setAddress(String address) {
  this.address = address;
 }

 @Override
 public String toString() {
  return this.id + ", " + this.name + ", " + this.address;
 }
}
Below one is the traditional sorting technique
Collections.sort(persons, new Comparator<Person>() {
   public int compare(Person p1, Person p2) {
    return p1.getName().compareTo(p2.getName());
   }
  });



Here is the implementation using Java 8 using Lambda expression
Collections.sort(persons, (p1, p2) -> p1.getName().compareTo(p2.getName()));

Collections.sort(persons, (Person p1, Person p2) -> p1.getName().compareTo(p2.getName()));

persons.sort((p1, p2) -> p1.getName().compareTo(p2.getName()));

// Here, specifically the sorted list need to be assigned to a new list
// or existing list object.  
persons = persons.stream().sorted((p, p2) -> (p.getName().compareTo(p2.getName())))
 .collect(Collectors.toList());


Finally print the list using lambda expression
persons.forEach((person) -> System.out.print(person + "\n"));


Output
IdOne, Andy, Netherland
IdThree, Chris, London
IdTwo, John, Australia
IdFour, Nathan, Paris
IdFive, Peter, Brazil