Java 8 Lambda : Comparator example

java-lambda-expression

In this example, we will show you how to use Java 8 Lambda expression to write a Comparator to sort a List.

1. Classic Comparator example.


	Comparator<Developer> byName = new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getName().compareTo(o2.getName());
		}
	};

2. Lambda expression equivalent.


	Comparator<Developer> byName = 
		(Developer o1, Developer o2)->o1.getName().compareTo(o2.getName());

1. Sort without Lambda

Example to compare the Developer objects using their age. Normally, you use Collections.sort and pass an anonymous Comparator class like this :

TestSorting.java

package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TestSorting {

	public static void main(String[] args) {

		List<Developer> listDevs = getDevelopers();

		System.out.println("Before Sort");
		for (Developer developer : listDevs) {
			System.out.println(developer);
		}
		
		//sort by age
		Collections.sort(listDevs, new Comparator<Developer>() {
			@Override
			public int compare(Developer o1, Developer o2) {
				return o1.getAge() - o2.getAge();
			}
		});
	
		System.out.println("After Sort");
		for (Developer developer : listDevs) {
			System.out.println(developer);
		}
		
	}

	private static List<Developer> getDevelopers() {

		List<Developer> result = new ArrayList<Developer>();

		result.add(new Developer("mkyong", new BigDecimal("70000"), 33));
		result.add(new Developer("alvin", new BigDecimal("80000"), 20));
		result.add(new Developer("jason", new BigDecimal("100000"), 10));
		result.add(new Developer("iris", new BigDecimal("170000"), 55));
		
		return result;

	}
	
}

Output


Before Sort
Developer [name=mkyong, salary=70000, age=33]
Developer [name=alvin, salary=80000, age=20]
Developer [name=jason, salary=100000, age=10]
Developer [name=iris, salary=170000, age=55]

After Sort
Developer [name=jason, salary=100000, age=10]
Developer [name=alvin, salary=80000, age=20]
Developer [name=mkyong, salary=70000, age=33]
Developer [name=iris, salary=170000, age=55]

When the sorting requirement is changed, you just pass in another new anonymous Comparator class :


	//sort by age
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getAge() - o2.getAge();
		}
	});
	
	//sort by name	
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getName().compareTo(o2.getName());
		}
	});
				
	//sort by salary
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getSalary().compareTo(o2.getSalary());
		}
	});				

It works, but, do you think it is a bit weird to create a class just because you want to change a single line of code?

2. Sort with Lambda

In Java 8, the List interface is supports the sort method directly, no need to use Collections.sort anymore.


        //List.sort() since Java 8
	listDevs.sort(new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o2.getAge() - o1.getAge();
		}
	});	

Lambda expression example :

TestSorting.java

package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class TestSorting {

	public static void main(String[] args) {

		List<Developer> listDevs = getDevelopers();
		
		System.out.println("Before Sort");
		for (Developer developer : listDevs) {
			System.out.println(developer);
		}
		
		System.out.println("After Sort");
		
		//lambda here!
		listDevs.sort((Developer o1, Developer o2)->o1.getAge()-o2.getAge());
	
		//java 8 only, lambda also, to print the List
		listDevs.forEach((developer)->System.out.println(developer));
	}

	private static List<Developer> getDevelopers() {

		List<Developer> result = new ArrayList<Developer>();

		result.add(new Developer("mkyong", new BigDecimal("70000"), 33));
		result.add(new Developer("alvin", new BigDecimal("80000"), 20));
		result.add(new Developer("jason", new BigDecimal("100000"), 10));
		result.add(new Developer("iris", new BigDecimal("170000"), 55));
		
		return result;

	}
	
}

Output


Before Sort
Developer [name=mkyong, salary=70000, age=33]
Developer [name=alvin, salary=80000, age=20]
Developer [name=jason, salary=100000, age=10]
Developer [name=iris, salary=170000, age=55]

After Sort
Developer [name=jason, salary=100000, age=10]
Developer [name=alvin, salary=80000, age=20]
Developer [name=mkyong, salary=70000, age=33]
Developer [name=iris, salary=170000, age=55]

3. More Lambda Examples

3.1 Sort By age


	//sort by age
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getAge() - o2.getAge();
		}
	});
	
	//lambda
	listDevs.sort((Developer o1, Developer o2)->o1.getAge()-o2.getAge());
	
	//lambda, valid, parameter type is optional
	listDevs.sort((o1, o2)->o1.getAge()-o2.getAge());

3.2 Sort by name


	//sort by name
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getName().compareTo(o2.getName());
		}
	});
		
	//lambda
	listDevs.sort((Developer o1, Developer o2)->o1.getName().compareTo(o2.getName()));		
	
	//lambda
	listDevs.sort((o1, o2)->o1.getName().compareTo(o2.getName()));		

3.3 Sort by salary


	//sort by salary
	Collections.sort(listDevs, new Comparator<Developer>() {
		@Override
		public int compare(Developer o1, Developer o2) {
			return o1.getSalary().compareTo(o2.getSalary());
		}
	});				

	//lambda
	listDevs.sort((Developer o1, Developer o2)->o1.getSalary().compareTo(o2.getSalary()));
	
	//lambda
	listDevs.sort((o1, o2)->o1.getSalary().compareTo(o2.getSalary()));

3.4 Reversed sorting.

3.4.1 Lambda expression to sort a List using their salary.


	Comparator<Developer> salaryComparator = (o1, o2)->o1.getSalary().compareTo(o2.getSalary());
	listDevs.sort(salaryComparator);

Output


Developer [name=mkyong, salary=70000, age=33]
Developer [name=alvin, salary=80000, age=20]
Developer [name=jason, salary=100000, age=10]
Developer [name=iris, salary=170000, age=55]

3.4.2 Lambda expression to sort a List using their salary, reversed order.


	Comparator<Developer> salaryComparator = (o1, o2)->o1.getSalary().compareTo(o2.getSalary());
	listDevs.sort(salaryComparator.reversed());

Output


Developer [name=iris, salary=170000, age=55]
Developer [name=jason, salary=100000, age=10]
Developer [name=alvin, salary=80000, age=20]
Developer [name=mkyong, salary=70000, age=33]

References

  1. Start Using Java Lambda Expressions
  2. Oracle : Lambda Expressions
  3. Oracle : Comparator

44 comments on “Java 8 Lambda : Comparator example

  1. Sorry brother i mean classes are not properly organize missed dependency class file in some of your articles. You article are great, but if you can organize the java code in proper place it would be great. Thank you so much for sharing.

    1. package com.avi.lamda;

      import java.math.BigDecimal;

      public class Developer {
      private String name;
      private BigDecimal salary;
      private int age;
      public Developer(String name, BigDecimal salary, int age) {

      this.name=name;
      this.salary=salary;
      this.age=age;
      }
      public String getName() {
      return name;
      }
      public void setName(String name) {
      this.name = name;
      }
      public BigDecimal getSalary() {
      return salary;
      }
      public void setSalary(BigDecimal salary) {
      this.salary = salary;
      }
      public int getAge() {
      return age;
      }
      public void setAge(int age) {
      this.age = age;
      }

      public String toString() {
      return name+” “+salary+” “+age;
      }
      }

      1. Keeping data members private and trying to use comparator (lambda or otherwise) is not going to work as it won’t be able to access the private field. Either make them public or default, or implement Comparable and override compareTo.

  2. Is it possible to have the complete list of files by link? Because following your tutorial I have a lot of problem, thanks

      1. humans.sort((h1, h2) -> {
        if (h1 == null) {
        return h2 == null ? 0 : 1;
        }
        else if (h2 == null) {
        return -1;
        }
        return h1.getName().compareTo(h2.getName());
        });

  3. The lambda comparator example can be simplified slightly by omitting the class declaration:

    Comparator byName =
    (o1, o2)->o1.getName().compareTo(o2.getName());

  4. I am not able get the output as mentioned here (sorting with out lambada)
    I have complied and executed above program in eclipse mar and the output is
    Before Sort
    javatpointegs.Comparatoreg$Developer@15db9742
    javatpointegs.Comparatoreg$Developer@6d06d69c
    javatpointegs.Comparatoreg$Developer@7852e922
    javatpointegs.Comparatoreg$Developer@4e25154f
    After Sort
    javatpointegs.Comparatoreg$Developer@15db9742
    javatpointegs.Comparatoreg$Developer@6d06d69c
    javatpointegs.Comparatoreg$Developer@7852e922
    javatpointegs.Comparatoreg$Developer@4e25154f

  5. I find that I keep coming back here, because your Java 8 examples are the best. You keep it simple and focused, much more so than the other examples out there.

  6. Got me too long to find information like this on other sites until I reached this article. Thanks, very informative 🙂

  7. Actually, we can do it even simplier. Instead of writing for example

    Comparator salaryComparator = (o1, o2)->o1.getSalary().compareTo(o2.getSalary());
    listDevs.sort(salaryComparator.reversed());

    you can shorten this using “comparing” factory method combined with method reference:

    listDevs.sort(Comparator.comparing(Developer::getSalary()).reversed());

    after static import:

    listDevs.sort(comparing(Developer::getSalary()).reversed());

    1. Thanks for your example, The “()” from getSalary() will prompts error, just remove it.

      listDevs.sort(Comparator.comparing(Developer::getSalary));

  8. Hi,

    In Java 8 you could print the list of developers like this :
    listDevs.forEach(System.out::println);

    Instead of :
    listDevs.forEach((developer)->System.out.println(developer));

    Romain.

    1. i could format my output like below say if my list is “Integers” (list having 100,10,222,3000,40000)

      i can use
      listInts.forEach((i)->System.out.println(i+”,”));

      using method references all integers will be appended and displayed, but can i use “,” as above using method references

      ?? – any idea

Leave a Comment

Your email address will not be published. Required fields are marked *