If anyone finds a mistake, please kindly point it out.
I myself was very confused because I couldn't organize my mind at all while studying for the Java Gold exam, so I organized it as a reflection. I feel like I'm getting along a little with this ٩ ('ω') و
What are Comparable and Comparator? However, it is an interface used for mutual comparison of elements in both sorting and minimum / maximum value acquisition methods. Well, I understand that ... I feel like.
I wonder if it's in ascending order. With that understanding, I wasn't sure. However, just by pinpointing what this is, the hurdle to understanding will be significantly lowered. Therefore, please let me enter from the explanation here first.
This "natural ordering" comes up frequently when browsing the Java API documentation. However, as you can see by looking at it, "natural ordering" and "comparator" are already introduced like set products.
I'm sure there are some people who come up with a pin here, but natural ordering means sorting in the order implemented by Comparable. Below is an excerpt of the Comparable Java API documentation.
public interface Comparable
Forces global ordering on objects of each class that implements this interface. This ordering is called the natural ordering of the class, and the compareTo method of this class is called the natural comparison method. Java API documentation-Comparable
So what is Comparable? As a position, it seems to be a common method of class (object). Speaking of common methods, equals and toString may have come to mind. However, unlike others, Comparable is not declared in Object. Therefore, it is necessary to implement it at the time of class creation if necessary. Note that if you try to sort according to natural ordering without implementing Comparable, a "ClassCastException" will occur, so be careful if the target class implements Comparable.
By the way, it can be implemented in ascending or descending order, but there are some methods that sort by natural ordering that are clearly described as "ascending order" (sorts class sort, etc.), so natural ordering is probably based on ascending order implementation. I wonder if it is.
Comparator is an interface that came out after Comparable. I presume that the main uses are probably as follows.
-I want to sort classes or fields for which Comparable is not implemented. ・ I want to do a little special sorting
And, perhaps to meet these expectations, Comparator is a "functional interface" that can be implemented flexibly. In addition, a static method that can simplify the implementation is also provided, and it seems that you may use the static method of Comparator to implement Comparable (laugh)
Also, if Comparator is null, it seems that the method applies Comparable or gives a "NullPointerException".
If you think only as a test preparation, I think that there is no problem if you remember the extreme theory as follows. There were some methods that did not allow Comparable, but I wonder if it is OK to remember the basics as a set.
On top of that, if you remember the difference in each implementation (difference in method name and number of arguments), Yoshi!
The following is a summary of the differences between the implementations. Keep in mind that the methods and the number of arguments to override are mandatory for the exam.
package | interface | Abstract method | Number of arguments | Return type | Description |
---|---|---|---|---|---|
java.lang | Comparable | compareTo | 1 | int | Compare itself with the argument object. Used for natural ordering |
java.util | Comparator | compare | 2 | int | Compare the arguments. Arbitrary ordering |
I will introduce a concrete implementation example from the next section.
We will introduce each implementation example. Also, if possible, we recommend that you check it on the actual machine.
↓ ↓ The sample to be introduced should move quickly with copy and paste below Java cloud execution environment: https://paiza.io/
Comparable As explained earlier, implement Comparable for the corresponding class. The implementation example is as follows.
class Book implements Comparable<Book> { //Implementation declaration.<>The inside is for comparison.
public Integer id;
public String title;
Book(Integer id, String title){
this.id = id;
this.title = title;
}
@Override
public int comareTo(Book book){ //Comparable abstract methods
return this.id.compareTo(book.id); //Compare arguments with yourself
}
}
The compareTo method returns a negative integer if it is less than the specified object, zero if it is equal, and a positive integer if it is greater. By the way (?), What is compareTo in the compareTo method? Am I the only one who thinks?
Now let's sort using Comparable.
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
//Creating a sort target
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(3, "Hamster breeding diary"));
bookList.add(new Book(2, "Howl's Moving Castle"));
bookList.add(new Book(1, "Harry potter"));
//Sort execution
bookList.sort(); //Since no argument is specified, it is naturally ordered according to Comparable.
//Display the sort target
bookList.forEach( s -> System.out.println(s.id + ":" + s.title));
}
}
<Execution result>
1:Harry potter
2:Howl's Moving Castle
3:Hamster breeding diary
Looking at this, I am vaguely wondering if it is an implementation because there are generics.
And you who became interested in Comparable. Please know more (exactly) in the Java API docs ٩ ('ω') و ← thrown
Java API documentation-Comparable interface
Comparator Now let's move on to Comparator. Since this is a "functional interface", various implementation methods can be taken. As far as I can tell, I will introduce each sample.
This is almost the same as Comparable. I don't think it makes much sense to use the Comparator in this way. Personally. ..
class Book implements Comparator<Book> { //① Implementation declaration.<>The inside is for comparison.
public Integer id;
public String title;
Book(){} //① Without this, you will get angry when you make a new
Book(Integer id, String title){
this.id = id;
this.title = title;
}
public int getId(){ // ②Comparator.Used as an argument for comparing
return this.id;
}
public String getTitle(){ // ②Comparator.used as an argument to thenComparing
return this.title;
}
@Override
public int compare(Book book1, Book book2){ //① Abstract method of Comparator interface
return book1.id - book2.id; //Sort by id in ascending order
}
}
The compare method compares the two arguments for ordering. Returns a negative integer if the first argument is less than the second argument, 0 if both are equal, and a positive integer if the first argument is greater than the second argument.
Let's sort by the implemented Comparator. I was shocked (?) At first glance, but in the case of implementation in a class, Comparator "news the class that implements Comparator" and passes it. Ah ... I'm going to get angry if I give a Comparator of a type different from the type to be sorted ... Ah ... I got angry (what)
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(3, "Hamster breeding diary"));
bookList.add(new Book(2, "Howl's Moving Castle"));
bookList.add(new Book(1, "Harry potter"));
bookList.sort(new Book()); //← [Note] Be sure to remember because the way to pass the Comparator is special! Pass an instance of the class that contains the Comparator! !! !!
bookList.forEach( s -> System.out.println(s.id + ":" + s.title));
}
}
<Execution result>
1:Harry potter
2:Howl's Moving Castle
3:Hamster breeding diary
It is a writing style that can fully demonstrate that it is a functional interface. What you can write in lambda expression can be written in anonymous class, so I will introduce both.
** Lambda expression implementation sample **
Comparator<Book> comparator =
(b1, b2) -> b1.id.compareTo(b2.id); //Ascending order of id
** Anonymous class implementation sample **
Comparator<Book> comparator = new Comparator<Book>(){
@Override
public int compare(Book book1, Book book2) {
return book1.id.compareTo(book2.id); //Ascending order of id
}
};
Now let's perform a sort. This implements Comparator directly without making it variable.
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
//Create a sort target
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(3, "Hamster breeding diary"));
bookList.add(new Book(2, "Howl's Moving Castle"));
bookList.add(new Book(1, "Harry potter"));
//Comparator(Anonymous class)Sort execution using
bookList.sort(new Comparator<Book>(){
@Override
public int compare(Book book1, Book book2) {
return book1.id.compareTo(book2.id); //Ascending order of id
}
});
//Display sort results
System.out.println("Anonymous class(Ascending order of id)");
bookList.forEach( s -> System.out.println(s.id + ":" + s.title));
//Comparator(Lambda expression)Sort execution using * Arrange in descending order for easy understanding
bookList.sort((b1, b2) -> b2.id.compareTo(b1.id)); //id descending
//Display sort results
System.out.println("Lambda expression (descending order of id)");
bookList.forEach( s -> System.out.println(s.id + ":" + s.title));
}
}
<Execution result>
Anonymous class(Ascending order of id)
1:Harry potter
2:Howl's Moving Castle
3:Hamster breeding diary
Lambda expression(id descending)
3:Hamster breeding diary
2:Howl's Moving Castle
1:Harry potter
Comparator provides convenient static methods. You can also prioritize the members to be sorted by combining this static method. For simple sorting, I think it's easiest to use this guy. (what
The sample using Stream API is as follows.
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) throws Exception {
//Create a sort target
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(2, "Hamster breeding diary"));
bookList.add(new Book(2, "Howl's Moving Castle"));
bookList.add(new Book(1, "Harry potter"));
//Stream
Stream<Book> streamList = bookList.stream();
//Comparator.Sort and display using comparing
streamList.sorted(Comparator.comparing(Book::getId) //Sort ids first
.thenComparing(Book::getTitle)) //Sort titles with second priority
.forEach(s -> System.out.println(s.id + ":" + s.title));
}
}
<Execution result>
1:Harry potter
2:Howl's Moving Castle
2:Hamster breeding diary
Compare () and thenComparing () are used in a chain. Of course, you can use comparing () alone, or you can chain thenComparing () further. Also, while saying that the correction is static, thenComparing () is a defalt method ^^; In addition, Comparator provides the following methods.
# | Method name | Description |
---|---|---|
① | comparing | Takes a function that extracts the sort key and returns a comparator that compares with that sort key |
② | thenComparing | Returns the lexicographic order comparator with the other comparator |
③ | naturalOrder | Returns a comparator that compares Comparable objects in natural order (defalt method) |
④ | nullsFirst | Returns a null-friendly comparator that considers null to be less than non-null |
⑤ | nullsFirst | Returns a null-friendly comparator that considers null to be greater than non-null |
⑥ | reversed | I will return a comparator that requires the reverse order of this comparator(default method) |
⑦ | reverseOrder | Returns a comparator that mandates the reverse of natural ordering |
And if you are interested, please refer to the Java API documentation. My explanation is rough (laughs) Java API documentation-Comparator interface
So far, we have seen examples using Comparator, but if it is made the same as Comparator, it seems that it can actually be used with other methods without problems. I felt like something was wrong, but it's probably the same as using the static method of Comparator.
Let's actually see an example. First, create a class that will replace Compartor.
class LengthChecker {
public static int check(Book b1, Book b2){ //Can be a static method unlike the compare method that is overridden when implementing Comparator
return b1.title.length() - b2.title.length(); //title Ascending order of number of characters
}
}
After creating it, pass it as an argument to the method instead of Comparator.
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
//Create a sort target
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(2, "Hamster breeding diary"));
bookList.add(new Book(2, "Howl's Moving Castle"));
bookList.add(new Book(1, "Harry potter"));
//Perform a sort
bookList.sort(LengthChecker::check); //← Unlike Comparator, it is necessary to specify the method
//Display sort results
bookList.forEach(s -> System.out.println(s.id + ":" + s.title));
}
}
<Execution result>
2:Howl's Moving Castle
1:Harry potter
2:Hamster breeding diary
It's working well ... eh x ah sdf ... Basically, the place where Comparator is specified in the argument seems to be replaced. I haven't researched the specifications of this area, but it was a problem, so it may be better to remember it as much as "he". However, it seems that there are restrictions. As a result of various trials, it probably looks like this.
Introducing methods that use Comparable and Comparator to sort and get large and small elements. It's super easy to write, so please refer to the Java API documentation for details. Rather, it's a good idea to familiarize yourself with the Java API documentation during this time! !! !!
It is very often used in classes that implement this interface and in default / static methods. In addition, please read on the assumption that the Book class mentioned in the previous section is implemented.
A sorting method is provided as the default method.
# | Method name | Comparable | Comparator | Description |
---|---|---|---|---|
① | sort | - | ○ | I'll sort |
** Implementation sample **
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
//Create a sort target
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(3, "Hamster breeding diary"));
bookList.add(new Book(2, "Howl's Moving Castle"));
bookList.add(new Book(1, "Harry potter"));
//Sort to Comparator
bookList.sort(new Book());
}
}
Click here for details on the List interface (https://docs.oracle.com/javase/jp/8/docs/api/java/util/List.html)
The implementation class of the Collections interface defines all static methods.
# | Method name | Comparable | Comparator | Description |
---|---|---|---|---|
① | sort | ○ | ○ | I'll sort |
② | reverseOrder | ○ | ○ | Specified in the argument of sort. I'll sort in reverse order |
③ | reverse | ○ | - | 逆順にソ-トするよ |
④ | min | ○ | ○ | I will return the smallest element of the sorted result |
⑤ | max | ○ | ○ | I will return the maximum element of the sorted result |
** Implementation sample **
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
//Create a sort target
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(3, "Hamster breeding diary"));
bookList.add(new Book(2, "Howl's Moving Castle"));
bookList.add(new Book(1, "Harry potter"));
//Sort to Comparable
Collections.sort(bookList);
Collections.sort(bookList, Collections.reverseOrder());
Collections.reverse(bookList);
Collections.min(bookList);
Collections.max(bookList);
//Sort to Comparator
Collections.sort(bookList, new Book());
Collections.sort(bookList, Collections.reverseOrder(new Book()));
Collections.min(bookList, new Book());
Collections.max(bookList, new Book());
}
}
Click here for details on the Collections class [https://docs.oracle.com/javase/jp/8/docs/api/java/util/Collections.html)
Various methods are provided for manipulating arrays. All the methods introduced are static methods.
# | Method name | Comparable | Comparator | Description |
---|---|---|---|---|
① | sort | ○ | ○ | I'll sort |
② | parallelSort | ○ | ○ | Do you want to sort? |
③ | binarySearch | ○ | ○ | After sorting, do you search? |
** Implementation sample ** There are a lot of different types for each type, but it's a good idea. Please refer to the Java API documentation for details.
sample.java
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
//Create an array to sort
String[] array = {"Ham assistant","Ham child","Hamjiro"};
//Sort to Comparable
Arrays.sort(array);
Arrays.parallelSort(array);
Arrays.binarySearch(array, "Ham assistant"); //Comes out first after sorting in natural order"Ham assistant"Will tell you the index number of
//Create Comparator
Comparator<String> comparator = new Comparator<String>(){
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
};
//Sort to Comparator
Arrays.sort(array, comparator);
Arrays.parallelSort(array, comparator);
Arrays.binarySearch(array, "Ham assistant", comparator); //Comes out first after sorting by comparator"Ham assistant"Will tell you the index number of
}
}
Click here for details on the Arrays class [https://docs.oracle.com/javase/jp/8/docs/api/java/util/Arrays.html#sort-T:A-int-int-java.util .Comparator-)
Since it is a collection that supports sorting by default, sorting is performed when the constructor is called. After that, Comparable and Comparator will be activated every time an element is added.
【point】 If you're based on natural ordering, you won't feel the shadow of Comparable at all, but be aware that you'll get an exception if Comparable isn't implemented in your class! !! !!
** Implementation sample ** Since it will be similar, only TreeSet is sampled.
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
//Create Comparator
Comparator<Book> comparator = new Comparator<Book>(){
@Override
public int compare(Book b1, Book b2) {
return b1.getTitle().length() - b2.getTitle().length(); //Longest number of title characters
}
};
//Created in Comparable
TreeSet<Book> book = new TreeSet<>();
book.add(new Book(2, "Totoko Hamjiro"));
book.add(new Book(3, "The World Unknown To Matsuko"));
book.add(new Book(1, "Ham Festival from Monday"));
System.out.println("<Comparable>");
book.forEach( s -> System.out.println(s.getId() + ":" + s.getTitle()));
//Created in Comparator
TreeSet<Book> book2 = new TreeSet<>(comparator);
book2.add(new Book(2, "Totoko Hamjiro"));
book2.add(new Book(3, "The World Unknown To Matsuko"));
book2.add(new Book(1, "Ham Festival from Monday"));
System.out.println("<Comparator>");
book2.forEach( s -> System.out.println(s.getId() + ":" + s.getTitle()));
}
}
<Execution result>
<Comparable>
1:Ham Festival from Monday
2:Totoko Hamjiro
3:The World Unknown To Matsuko
<Comparator>
2:Totoko Hamjiro
1:Ham Festival from Monday
3:The World Unknown To Matsuko
Click here for details on TreeSet (https://docs.oracle.com/javase/jp/8/docs/api/java/util/Collections.html) / Click here for details on TreeMap (https://docs) .oracle.com/javase/jp/8/docs/api/java/util/TreeMap.html)
It is possible to perform operations such as sorting on streamed objects. You can also use the Collection and Map interface forces mentioned above.
# | Method name | Comparable | Comparator | Description |
---|---|---|---|---|
① | sort | ○ | ○ | sort |
② | min | - | ○ | ソ-トした結果の最小要素をOption型で返却 |
③ | max | - | ○ | ソ-トした結果の最大要素をOption型で返却 |
** Implementation sample **
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) throws Exception {
//Create a sort target
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(2, "Hamster breeding diary"));
bookList.add(new Book(2, "Howl's Moving Castle"));
bookList.add(new Book(1, "Harry potter"));
//Create Comparator
Comparator<Book> comparator = new Comparator<Book>(){
@Override
public int compare(Book b1, Book b2) {
return b1.getTitle().length() - b2.getTitle().length(); //Longest number of title characters
}
};
//Sort to Comparable
System.out.println("<Comparable:Shortest title>");
bookList.stream().sorted().forEach(s -> System.out.println(s.getId() + ":" + s.getTitle()));
//Sort to Comparator
System.out.println("<Comparator:Shortest title>");
bookList.stream().sorted(comparator).forEach(s -> System.out.println(s.getId() + ":" + s.getTitle())); //← here
Book minBook = bookList.stream().min(comparator).get(); //← here
System.out.println("<Book with the shortest title>");
System.out.println(minBook.getId() + ":" + minBook.getTitle());
Book maxBook = bookList.stream().max(comparator).get(); //← here
System.out.println("<Book with the longest title>");
System.out.println(maxBook.getId() + ":" + maxBook.getTitle());
}
}
<Execution result>
<Comparable:Shortest title>
2:Hamster breeding diary
2:Howl's Moving Castle
1:Harry potter
<Comparator:Shortest title>
2:Howl's Moving Castle
1:Harry potter
2:Hamster breeding diary
<Book with the shortest title>
2:Howl's Moving Castle
<Book with the longest title>
2:Hamster breeding diary
Click here for details on Stream API (https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html#sorted--)
JavaSE8Gold I'll give you a problem. First, there is the following code.
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(1, "Ham assistant"));
bookList.add(new Book(2, "Hamtaro"));
bookList.add(new Book(3, "Ham Jiro"));
Collections.sort(bookList); //← Here.
What code should I implement in my Book class to run this program and sort it in ascending order of Book.id?
// ①
public int compareTo(Book book){
return this.id.compareTo(book.id);
}
// ②
public boolean compareTo(Book book){
return this.id.compareTo(book.id);
}
// ③
public int compare(Book book1, Book book2){
return book1.id - book2.id;
}
// ④
public boolean compare(Book book1, Book book2){
return book1.id > book2.id;
}
・ ・ ・ ・
The correct answer is ①! Since we didn't pass a Comparator as an argument, it's a sort by natural ordering (Comparable). Comparable's abstract method is compareTo. Also, there is one argument and the return value is an int type.
After the test is over, you can look back slowly, but before the test, you are busy with Kuromoto laps and input, so you can not afford it ^^; ... I don't feel like I got more points if I did it before the exam (TvT)
I referred to the Java SE8 API documentation
Comparable Interface Comparator Interface Collections class List interface TreeMap class TreeSet class Arrays class Stream API class
Also, as I was studying for the exam, I also read purple and black books, so my knowledge of Sochira is also integrated.
Recommended Posts