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 theComparable<T>
interface and define this method. All Java classes that have a natural ordering implementComparable<T>
- Example:String
, wrapper classes,BigInteger
compare(a, b)
:
Comparator interface : Compares values of two objects. This is implemented as part of theComparator<T>
interface, and the typical use is to define one or more small utility classes that implement this, to pass to methods such assort()
or for use by sorting data structures such asTreeMap
andTreeSet
. 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.
- 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
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 Comparator
s 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 String
s 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 comparesFruit
s based on theirsize
. This is a custom implementation. Collections.max
will invokecompareTo
a number of times related to the size of your collection, to infer themax
item in the collection, hencecompareTo
is invoked.Object#equals
will be invoked when invokingequals
in your example, as it is not overridden inFruit
.- The equality will be tested between the "largest" fruit in your collection, and the second
Apple
you declared, i.e. between the sameApple
with size2
in this case. It should returntrue
.
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
Different Dependencies for Different Build Profiles
Java Function for Arrays Like PHP's Join()
Junit: How to Simulate System.In Testing
Updating Java Priorityqueue When Its Elements Change Priority
How to Create a Custom Appender in Log4J2
Preemptive Basic Authentication with Apache Httpclient 4
Is Java.Sql.Connection Thread Safe
How to Generate a Random Biginteger Value in Java
What's the Syntax to Import a Class in a Default Package in Java
Test If Element Is Present Using Selenium Webdriver
Why Is String.Chars() a Stream of Ints in Java 8
Is It Expensive to Use Try-Catch Blocks Even If an Exception Is Never Thrown
Emulate Annotation Inheritance for Interfaces and Methods with Aspectj
How to Use Xpath on Xml Docs Having Default Namespace
How to Write Console Output to a Txt File