How does a comparator outperform a comparable one?

"How you will sort a collection of employee objects by its identifier or name." For this we can use two interfaces, i.e. Comparator and Comparable. this seems to be one of the common interview questions.

But I see no reason why I should use how to sort employee objects

I thought that comparator does Comparable cannot. I understand that if objects (instance variables that are compared) are in natural order, then Comparable is the right choice. but if an individual order is required (for example, string length), then you can write comparator. my point here is the comparator client needs only if he wants to sort the data according to some other criteria. For example, I would run an Employee class to sort id using a comparable interface . but if the client wants to sort Employee objects using String (name), he will implement the comparator either as a concrete class or anonymously when sorting. Is there something I don't see here?

For example, In the following code for the Person object, my compareTo method compares age and sorts it. In the comparison method, I use the string length (person name) to sort. Theoretically, I could execute both compareTo methods, as I already implemented below.

Finally, are there any additional benefits of one of the following I implemented the comparator in two ways 1. as a static method that is commented out 2. as an anonymous object (?) In the main method that is commented out 3. create a new class that implements the comparator and calls an instance of this class in .sort () collections - this I did not do here

 (The commented-out parts of the code works. They are just different implementations) mport java.util.Collections; import java.util.Comparator; import java.util.*; public class PersonComparator implements Comparable{ private String name; private int age; public PersonComparator(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "name=" + name + ", age=" + age; } /*@Override public int compareTo(Object obj) { if (!(obj instanceof PersonComparator)) { throw new ClassCastException("Invalid object"); } PersonComparator p2 = (PersonComparator)obj; return this.age-p2.age; }*/ /*Alternative CompareTo that checks for both age and name*/ public int compareTo(Object obj) { if (!(obj instanceof PersonComparator)) { throw new ClassCastException("Invalid object"); } PersonComparator p2 = (PersonComparator)obj; if (this.age!=p2.age){ return this.age-p2.age; } else { return (this.name.length()-p2.name.length()); } } /*public static Comparator nameLengthComparator = new Comparator() { @Override public int compare(Object obj1, Object obj2) { if (!(obj1 instanceof PersonComparator) || !(obj2 instanceof PersonComparator)){ throw new ClassCastException("Invalid object"); } else { PersonComparator p1 = (PersonComparator)obj1; PersonComparator p2 = (PersonComparator)obj2; return p1.name.length()-p2.name.length(); } } };*/ public static void main(String[] args){ PersonComparator p1 = new PersonComparator("Alexander", 45); PersonComparator p2 = new PersonComparator("Pat", 27); PersonComparator p3 = new PersonComparator("Zacky", 45); PersonComparator p4 = new PersonComparator("Rake", 34); List<PersonComparator> list = new ArrayList<PersonComparator>(); list.add(p1); list.add(p2); list.add(p3); list.add(p4); System.out.println("Before sorting "+ list); Collections.sort(list); //System.out.println("After sorting by age "+ list); //System.out.println("Before sorting "+ list); //Collections.sort(list, nameLengthComparator); System.out.println("After sorting by name length "+ list); /*Collections.sort(list, new Comparator<PersonComparator>() { @Override public int compare(PersonComparator p1, PersonComparator p2) { return p1.name.length()-p2.name.length(); } } );*/ System.out.println("After sorting by name length "+ list); } } 

thanks

+4
source share
7 answers

Comparable interface

The Comparable interface defines the natural ordering of a type. Suppose you have a list of String or Integer objects; you can pass this list to

 Collections.sort(list); 

and you will have a sorted list. How? Because String and Integer implement the Comparable interface, and implementations of the Comparable interface provide a natural order. This is similar to a class definition: " If you find a collection of objects of my type, order them according to the strategy that I defined in the compareTo method ."

Now that you define your own type, you can define the natural order of the objects in your class by implementing the Comparable interface. See the Java documentation for more information on organizing objects .

Comparator interface

The Comparator interface describes how to define custom strategies for organizing objects. Suppose we have a simple Person type, as shown below:

 public class Person { String name; public Person(String name) { this.name = name; } public String getName() { return name; } } 

Now, implementing the Comparator interface, you can write different strategies for ordering instances of your Person type. For example, consider two strategies for organizing Person objects, as shown below:

 class StrategyOne implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { return p1.getName().length() - p2.getName().length(); } } class StrategyTwo implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { return p1.getName().compareTo(p2.getName()); } } 

Here StrategyOne will order Person objects based on the length of their names, and StrategyTwo will order Person objects based on the lexicographic ordering of their names.

Comparator Implementation Methods

As you can see, specific strategy classes are stateless, so all instances are functionally equivalent. Thus, we need only one instance of any particular strategy class. Thus, it must be singleton. Using anonymous classes will create a new instance each time a call is made. Consider storing the object in a closed static destination field and reusing it using static factory methods to access them . For example, you can reuse the two above strategies:

 class Strategies { private static final Comparator<Person> PERSON_NAME_LENGTH_COMPARATOR = new StrategyOne(); private static final Comparator<Person> PERSON_NAME_LEXICAL_COMPARATOR = new StrategyTwo(); public static Comparator<Person> personNameLengthComparator(){ return PERSON_NAME_LENGTH_COMPARATOR; } public static Comparator<Person> personNameLexicalComparator(){ return PERSON_NAME_LEXICAL_COMPARATOR; } } 

Summary

To summarize, the Comparable interface Comparable used to determine the natural ordering of the class, and the Comparator interface is used to define specific strategies for ordering objects.

+6
source

How does a comparator outperform a comparable one?

It is not "excellent." Just two interfaces do (roughly) the same thing in different ways. In the case of Comparable ordering logic resides in an ordered object. In the case of Comparator logic is in a different class from the declared objects.

But I see no reason why I should use how to sort employee objects

The only case where it would be advisable to use both options would be if you had to sort the objects in different orders. You can then declare the corresponding classes as implementing Comparable for the "natural" order and use Comparator objects to implement other orders.

By the way, the comparator probably should not implement Comparable , and vice versa.

If the comparator implements Comparable , which implies that you are trying to order instances of the comparator object itself ...

Your PersonComparator class PersonComparator not specified. It really should be called Person .


Could you clarify one thing in your answer that we already have the equals() method from the Object class, and then why does the Comparator interface make the equals() method easier?

Number of points:

  • You seem to be confusing the goal of Comparable and Comparator . The equals method of the Comparator object compares the comparator with other comparators !!

  • The equals method tells you if two objects are equal ... not the first.

  • The reason Comparator overrides equals is only because they can clearly document what equals(Object) does when you call it on a Comparator object. (The actual behavior is fully consistent with Object.equals(Object) ... but they obviously considered it necessary to do this because programmers repeatedly received the semantics of the method incorrectly.)

+7
source

How does a comparator outperform a comparable one?

I will not say that it is excellent, but one advantage is that it allows us to write several sorting sequences. In the case of Comparable you will have to implement this interface according to your class, which you want to sort, and you can write only one sort sequence.

With Comparator you can create different classes for sorting sequences, and when sorting, you simply pass an instance of Comparator to COllections.sort() .

Consider the Employee class, which has the fields id , firstName and lastName . If you implement Comparable , you can write only one sorting logic in the compareTo method.

If you implement Comparator , you can create separate sort sequences by creating separate classes. like IdSorter , FirstNameSorter and LastNameSorter , which gives you a way to sort Employee several ways.

Read

Sort custom objects using the Comparator

+4
source

Comparable allows you to sort items in collections on only one field. The comparator provides the flexibility to compare elements based on more than one field.

For instance.

 class Person implements Comparable { int age; String name; Person(int age,String name) { this.age=age; this.name=name; } public int compareTo(Object o1) // Either you can compare according to age or name { Person p = (Person)o1; if (this.age==p.age) return 0; else if (this.age>p.age) return 1; else return -1; } public int compareTo(Object o) //Based on name comparision { return (this.name.compareTo((Person)o).name)); } public static void main (String args[]) { List<Person> list = new ArrayList<Person>(); Person o = new Person(12,"Steve"); Person o1 = new Person(13,"Jason"); list.add(o); list.add(o1); Collections.sort(list); } } 

In the case of the comparison above, you can sort the items using either age or a name. But in the case of the Comparator, you can sort the elements based on more than one field.

 class AgeComparison implements Comparator { public int compare(Object o1,Object o2) { Person s1 = (Person)o1; Person s2 =(Person)o2; if (s1.age==s2.age) return 0; if(s1.age>s2.age) return 1; else return -1; } class NameComparison implements Comparator { public int compare(Object o1,Object o2) { Person s1 = (Person)o1; Person s2 =(Person)o2; return (s1.age.compareTo(s2.age)); } } 

To use Comparator, you need to pass a list and an instance of the class that you must use.

 Collections.sort(list,new NameComparison()); Collections.sort(list,new AgeComparison()); 

In short, the advantage of a comparator is the flexibility to sort a list based on more than one field of an object.

+3
source

Here you go ... I already wrote a lot about this clarification, helping photos and explanations.

Please find the link below:

Comparable and comparator

You might think that you can always remember, and that "they cannot be used interchangeably"

+1
source

In general, use Comparable when ordering is "obvious." For example, for strings that you use in alphabetical order, numbers are used in numerical order. Note that a Comparable object can implement only one compareTo () method, so you get only one option - the “natural”, “obvious” option. The advantage is that it is simple and the client code does not have to do any extra work to compare things.

Use Comparator if the order is less obvious or you may need several options. For example, a book can be sorted by title, author, ISBN, etc. You can have three different comparators to handle these three cases. You can sort the lines in an unusual order, for example. special case for a foreign language, ignoring capital, etc.

In addition, if the objects you sort do not implement Comparable, or you mix types that you don’t like to compare with each other (in general, this should be avoided, but you might want to be able to compare books and Authors in the same list in some special case) you need to use Comparator.

0
source

If you use a comparator, you just need to add one comparator class and pass it to the Collections.sort () method along with the List object, no other change to the existing code.

but if you implement a comparable interface, you will have to change the code of all model / bean classes to override the compareTo () method.

this is better for the Loose Coupling comparator.

0
source

Source: https://habr.com/ru/post/1499887/


All Articles