Differencebetween Compare() and Compareto()

What is the difference between compare() and compareTo()?

From JavaNotes:

  • a.compareTo(b):

    Comparable interface : Compares values and returns an int which tells if the values compare less than, equal, or greater than.

    If your class objects have a natural order, implement the Comparable<T> interface and define this method. All Java classes that have a natural ordering implement Comparable<T> - Example: String, wrapper classes, BigInteger

  • compare(a, b):

    Comparator interface : Compares values of two objects. This is implemented as part of the Comparator<T> interface, and the typical use is to define one or more small utility classes that implement this, to pass to methods such as sort() or for use by sorting data structures such as TreeMap and TreeSet. You might want to create a Comparator object for the following:

    • Multiple comparisons. To provide several different ways to sort something. For example, you might want to sort a Person class by name, ID, age, height, ... You would define a Comparator for each of these to pass to the sort() method.
    • System class To provide comparison methods for classes that you have no control over. For example, you could define a Comparator for Strings that compared them by length.
    • Strategy pattern To implement a Strategy pattern, which is a situation where you want to represent an algorithm as an object that you can pass as a parameter, save in a data structure, etc.

If your class objects have one natural sorting order, you may not need compare().


Summary from http://www.digizol.com/2008/07/java-sorting-comparator-vs-comparable.html

Comparable
A comparable object is capable of comparing itself with another object.

Comparator
A comparator object is capable of comparing two different objects. The class is not comparing its instances, but some other class’s instances.


Use case contexts:

Comparable interface

The equals method and == and != operators test for equality/inequality, but do not provide a way to test for relative values.

Some classes (eg, String and other classes with a natural ordering) implement the Comparable<T> interface, which defines a compareTo() method.

You will want to implement Comparable<T> in your class if you want to use it with Collections.sort() or Arrays.sort() methods.

Defining a Comparator object

You can create Comparators to sort any arbitrary way for any class.

For example, the String class defines the CASE_INSENSITIVE_ORDER comparator.


The difference between the two approaches can be linked to the notion of:

Ordered Collection:

When a Collection is ordered, it means you can iterate in the collection in a specific (not-random) order (a Hashtable is not ordered).

A Collection with a natural order is not just ordered, but sorted. Defining a natural order can be difficult! (as in natural String order).


Another difference, pointed out by HaveAGuess in the comments:

  • Comparable is in the implementation and not visible from the interface, so when you sort you don't really know what is going to happen.
  • Comparator gives you reassurance that the ordering will be well defined.

What is the difference between Comparable and operator compareTo?

Comparable is a standard interface, it's the way you define a class as having some ordering, and every library that deals with ordering works with Comparable types. Basically, if you want to be able to order and compare your things using all the standard functions and anything anyone else might write, you need to implement the Comparable interface.

This works:

data class SportsTeam(val name: String) : Comparable<SportsTeam> {
override fun compareTo(other: SportsTeam): Int = when {
name == "best team" -> 1
other.name == "best team" -> -1
else -> 0
}
}

fun main(args: Array<String>) {
val best = SportsTeam("best team")
val worst = SportsTeam("worst team")
print("The winner is: ${maxOf(best, worst).name}")
}

but because maxOf takes a Comparable type, this won't work:

data class SportsTeam(val name: String)

fun SportsTeam.compareTo(other: SportsTeam): Int = when {
name == "best team" -> 1
other.name == "best team" -> -1
else -> 0
}

fun main(args: Array<String>) {
val best = SportsTeam("best team")
val worst = SportsTeam("worst team")
print("The winner is: ${maxOf(best, worst).name}")
}

C#: What is the difference between CompareTo(String) and Equals(String)?

From MSDN:

string.CompareTo:

Compares this instance with a specified object or String and returns
an integer that indicates whether this instance precedes, follows, or
appears in the same position in the sort order as the specified object
or String.

string.Equals:

Determines whether two String objects have the same value.

In short, CompareTo is used for sorting. Equals is used to determine equality.

Difference between Comparable and Comparator?

Not really.

Comparable and Comparator are generic interfaces that allow to compare instances of the type defined in the generic (subclasses included).

The main difference between them is that Comparable is directly implemented in the class which you want to compare objects.

Consequently, if you have a single way to compare instances from a class, that is that you have a natural order for them, Comparable is the right approach.

On the other hand, if you have multiple ways to compare instances from a class, Comparable is not enough.

You should use Comparators instead (if it doesn't exist a natural order) or use both (if it exists a natural order and some other kinds of order).


Example where Comparator can be useful in addition to Comparable :

The String class implements Comparable by comparing two strings lexicographically.
Suppose you need to sort a List of String according to a different rule : their length.

You will need to define a Comparator<String> that implements this rule such as :

public class StringLengthComparator implements Comparator<String> {

@Override
public int compare(String o1, String o2) {
return Integer.compare(o1.length(), o2.length());
}

}

Now you could sort Strings by using their natural order (using Comparable) :

List<String> strings = new ArrayList<>();
...
strings.sort();

But you could also use a specific Comparator<String> :

strings.sort(new StringLengthComparator());

Or without creating any class with a lambda:

strings.sort((o1,o2)->Integer.compare(o1.length(), o2.length()));

Example where Comparator should be used instead of Comparable :

Suppose you have an Account class that represents a bank account.

Functionally you don't have a natural order to sort them but you have instead multiple orders according to the client needs.
Making the class to implement Comparable would not make sense. But creating distinct Comparator<Account> would.


Case where only Comparator can be used :

If you want to define a order for instances of a class which you cannot change the source code (JDK class or third party class), Comparator is the way to follow.

compareTo() vs. equals()

A difference is that "foo".equals((String)null) returns false while "foo".compareTo((String)null) == 0 throws a NullPointerException. So they are not always interchangeable even for Strings.

Usefulness of compareTo when comparing different case

The default case sensitive comparator is useful if you precisely want just that behavior: A case sensitive comparison between two strings. In fact, Ac is lexicographically larger than AD. If you want a case insensitive comparison, then use String#compareToIgnoreCase, for example:

String s1 = "Ac";
String s2 = "AD";

System.out.println(s1.compareToIgnoreCase(s2)); // -1 => Ac < AD, ignoring case

Relationship between equals and compareTo methods

  • Your compareTo method compares Fruits based on their size. This is a custom implementation.
  • Collections.max will invoke compareTo a number of times related to the size of your collection, to infer the max item in the collection, hence compareTo is invoked.
  • Object#equals will be invoked when invoking equals in your example, as it is not overridden in Fruit.
  • The equality will be tested between the "largest" fruit in your collection, and the second Apple you declared, i.e. between the same Apple with size 2 in this case. It should return true.

How to use compareTo() to compare two objects?

Your class needs to implement Comparable interface, and inside your class you need to override compareTo method (which is in Comparable interface). In this method you will define how your object will be compared to another, on what 'criteria' the comparison will be done.

It's a good practice to implement compareTo method such that, when its return value is 0, it's like two objects are equals (e.g. firstK.compareTo(secondK) == firstK.equals(secondK)).

You can also read Java documentation compareTo documentation.

public class K implements Comparable<K> {
//Attributes, constructor etc
@Override
public int compareTo(final K otherK) {
/*
Do what you want to compare them, for example, if your
K class has a integer field 'value', and you want to compare
K's instances based on 'value' field, you can do as follow:
*/
return Integer.compare(this.value, otherK.getValue());
}
}


Related Topics



Leave a reply



Submit