Whether to use Java Comparable or Comparator

The code for this article is written in ** JDK 1.8 **.

Introduction

When comparing objects of your own class, you need to define the comparison logic of what makes it big or small. There are the following two definition methods.

--Implement the Comparable interface in the object class and define it with the compareTo method. --Define a class that implements the Comparator interface and define it with the compare method.

It can be defined by either method, but there is a guideline for which one to define, so I will explain it.

Class to be compared

Consider comparing the Book class with the information in the book.

public class Book {

    //title
    private String title;

    //price
    private int price;

    //date of issue
    private LocalDate dateOfIssue;

}

Definition by Comparable

Implement the Comparable interface of java.lang and override the compareTo method to define the comparison logic. For example, if you want to compare with title, implement as follows.


public class Book implements Comparable<Book>{

    //title
    private String title;

    //price
    private int price;

    //date of issue
    private LocalDate dateOfIssue;

    @Override
    public int compareTo(Book book){
        return title.compareTo(book.title);
    }

}

The comparison result of title is returned as it is. Sorting the list of Book objects sorts them in ascending order of title.

** Sort example **

	Book book1 = new Book();
	book1.setTitle("Doraemon");
	book1.setPrice(500);
	book1.setDateOfIssue(LocalDate.of(2010,10,10));

	Book book2 = new Book();
	book2.setTitle("Perman");
	book2.setPrice(400);
	book2.setDateOfIssue(LocalDate.of(2012,10,10));

	Book book3 = new Book();
	book3.setTitle("Oba Q");
	book3.setPrice(300);
	book3.setDateOfIssue(LocalDate.of(2014,10,10));

	List<Book> bookList = Arrays.asList(book1, book2, book3);

	System.out.println("Before sorting:" + bookList);

	Collections.sort(bookList);

	System.out.println("After sorting:" + bookList);

sort (List <T> list) of java.util.Collections compares and sorts elements by compareTo of the element object.

Execution result

Before sorting:[Book(title=Doraemon, price=500, dateOfIssue=2010-10-10), Book(title=Perman, price=400, dateOfIssue=2012-10-10), Book(title=Oba Q, price=300, dateOfIssue=2014-10-10)]
After sorting:[Book(title=Oba Q, price=300, dateOfIssue=2014-10-10), Book(title=Doraemon, price=500, dateOfIssue=2010-10-10), Book(title=Perman, price=400, dateOfIssue=2012-10-10)]

Note that compareTo can only define ** one comparison logic **.

Definition by Comparator

Create a class that implements the Comparator of java.util and override the compare method to define the comparison logic. For example, if you want to compare with title, implement as follows.

public class BookTitleComparator implements Comparator<Book> {

    @Override
    public int compare(Book book1, Book book2){
        return book1.getTitle().compareTo(book2.getTitle());
    }

}

Let's sort using this.

** Sort example **

		Book book1 = new Book();
		book1.setTitle("Doraemon");
		book1.setPrice(500);
		book1.setDateOfIssue(LocalDate.of(2010,10,10));

		Book book2 = new Book();
		book2.setTitle("Perman");
		book2.setPrice(400);
		book2.setDateOfIssue(LocalDate.of(2012,10,10));

		Book book3 = new Book();
		book3.setTitle("Oba Q");
		book3.setPrice(300);
		book3.setDateOfIssue(LocalDate.of(2014,10,10));

		List<Book> bookList = Arrays.asList(book1, book2, book3);

		System.out.println("Before sorting:" + bookList);

		bookList.sort(new BookTitleComparator());

		System.out.println("After sorting:" + bookList);

Execution result

Before sorting:[Book(title=Doraemon, price=500, dateOfIssue=2010-10-10), Book(title=Perman, price=400, dateOfIssue=2012-10-10), Book(title=Oba Q, price=300, dateOfIssue=2014-10-10)]
After sorting:[Book(title=Oba Q, price=300, dateOfIssue=2014-10-10), Book(title=Doraemon, price=500, dateOfIssue=2010-10-10), Book(title=Perman, price=400, dateOfIssue=2012-10-10)]

You can create any number of classes that implement Comparator according to ** comparison logic ** as follows.

** Price comparison Comparator **

public class BookPriceComparator implements Comparator<Book> {

    @Override
    public int compare(Book book1, Book book2){
        return Integer.valueOf(book1.getPrice()).compareTo(book2.getPrice());
    }

}

** Issue date comparison Comparator **

public class BookDateOfIssueComparator implements Comparator<Book> {

    @Override
    public int compare(Book book1, Book book2){
        return book1.getDateOfIssue().compareTo(book2.getDateOfIssue());
    }

}

Postscript

If you use the static method comparing of Comparator, you don't even need to create a class.


//Title order
bookList.sort(Comparator.comparing(Book::getTitle));

//By price
bookList.sort(Comparator.comparing(Book::getPrice));

//By issue date
bookList.sort(Comparator.comparing(Book::getDateOfIssue));

So which one do you use?

From the conclusion, I think it is ** basically better to use Comparator **.

Since Comparable can only define one compareTo that belongs to a class, it is said that you should implement the comparison logic that seems most natural for that class. For example, LocalDate seems to be a natural comparison between dates, so compareTo is implemented in the "previous date <after date" logic.

So in which field is it natural to compare in this Book? Is it a title somehow? It seems that, depending on the person, the comparison by publication date may be natural, and if a field such as bookId is added in the future, it will be even more blurry, right? I only have a feeling of a bug.

Comparator can ** clearly specify what the comparison is with the class name **, so you can prevent such blurring. Also, if you want to make a complex comparison such as comparing by publication date if the titles are the same, you can add a separate Comparator implementation class.

Summary

--The comparison logic in Comparable should be a natural comparison, but what is natural depends on the situation. --Comparator can specify the content of comparison logic by the class name to be implemented. --In Comparable, only one comparison logic can be implemented, but in Comparator, as many as the number of classes can be implemented. --Basically, let's implement the comparison logic between your own classes with Comparator!

reference

[Introduction to Java-From basics in modern style to object-oriented and practical libraries](https://www.amazon.co.jp/Java%E6%9C%AC%E6%A0%BC%E5%85%A5%] E9% 96% 80-% EF% BD% 9E% E3% 83% A2% E3% 83% 80% E3% 83% B3% E3% 82% B9% E3% 82% BF% E3% 82% A4% E3 % 83% AB% E3% 81% AB% E3% 82% 88% E3% 82% 8B% E5% 9F% BA% E7% A4% 8E% E3% 81% 8B% E3% 82% 89% E3% 82 % AA% E3% 83% 96% E3% 82% B8% E3% 82% A7% E3% 82% AF% E3% 83% 88% E6% 8C% 87% E5% 90% 91% E3% 83% BB % E5% AE% 9F% E7% 94% A8% E3% 83% A9% E3% 82% A4% E3% 83% 96% E3% 83% A9% E3% 83% AA% E3% 81% BE% E3 % 81% A7-% E8% B0% B7% E6% 9C% AC-% E5% BF% 83-ebook / dp / B071D8RYR5) Comparable (Java Platform SE 8 ) Comparator (Java Platform SE 8 )

Recommended Posts

Whether to use Java Comparable or Comparator
[Java] How to use Map
[Java] How to use Map
How to use java Optional
How to use java class
[Java] How to use Optional ②
[Java] How to use removeAll ()
[Java] How to use string.format
How to use Java Map
[java] Reasons to use static
How to use Java variables
[Java] How to use Optional ①
How to use Java HttpClient (Get)
How to use Java HttpClient (Post)
[Java] How to use join method
[Processing × Java] How to use variables
[Java] How to use LinkedHashMap class
[JavaFX] [Java8] How to use GridPane
How to use class methods [Java]
[Java] How to use List [ArrayList]
How to use classes in Java?
[Processing × Java] How to use arrays
How to use Java lambda expressions
[Java] How to use Math class
How to use Java enum type
[Java8] Proper use of Comparable and Comparator in terms of employee sorting
Multilingual Locale in Java How to use Locale
[Java] How to use the File class
Use TMDA to parse IBM Java javacore
[Java] How to use the hasNext function
Java Artery-Easy to use unit test library
How to use submit method (Java Silver)
[Java] How to use the HashMap class
[Easy-to-understand explanation! ] How to use Java instance
[Java] How to use the toString () method
Studying how to use the constructor (java)
How to remote debug Java 9 or later
[Processing × Java] How to use the loop
How to use Java classes, definitions, import
[Easy-to-understand explanation! ] How to use Java polymorphism
[Java] [Maven3] Summary of how to use Maven3
[Processing × Java] How to use the class
How to use Java Scanner class (Note)
[Processing × Java] How to use the function
[Easy-to-understand explanation! ] How to use ArrayList [Java]
[Java] How to use the Calendar class
[Java] Learn how to use Optional correctly
[Easy-to-understand explanation! ] How to use Java overload
try-catch-finally exception handling How to use java
[Easy-to-understand explanation! ] How to use Java encapsulation
Use jenv to enable multiple versions of Java
[Java] How to use FileReader class and BufferedReader class
[Java] How to use Thread.sleep to pause the program
How to use Java framework with AWS Lambda! ??
I want to use java8 forEach with index
How to use Java API with lambda expression
Use Matplotlib from Java or Scala with Matplotlib4j
[Easy-to-understand explanation! ] How to use Java inheritance [Override explanation]
[Java] Introduction to Java
How to use the replace () method (Java Silver)
[Java] Use Collectors.collectingAndThen