If enum implements Comparable so why can't compare with < or >?
public class Dream
{
public static void main(String... args)
{
System.out.println(PinSize.BIG == PinSize.BIGGER); //false
System.out.println(PinSize.BIG == PinSize.BIG); //true
System.out.println(PinSize.BIG.equals(PinSize.BIGGER));//false
System.out.println(PinSize.BIG > PinSize.BIGGERER);// compilation error
//can't be compared
System.out.println(PinSize.BIG.toString().equals(PinSize.BIGGER));// #4
PinSize b = PinSize.BIG ;
System.out.println( b instanceof Comparable);// true
}
}
enum PinSize { BIG, BIGGER, BIGGERER };
You can do this:
PinSize.BIGGEST.ordinal() > PinSize.BIG.ordinal() // evaluates to `true`
Of course, assuming that BIGGEST was declared after BIG in the enumeration. The ordinal value in an enumeration is implicitly tied to the declaration order, by default the first value is assigned value 0, the second value 1 and so on.
So if yo declared the enumeration like this, things will work:
public enum PinSize {
SMALLEST, // ordinal value: 0
SMALL, // ordinal value: 1
NORMAL, // ordinal value: 2
BIG, // ordinal value: 3
BIGGER, // ordinal value: 4
BIGGEST; // ordinal value: 5
}
Implementing Comparable doesn't mean that you can use < or >. You can only use those with numeric values.
Implementing Comparable means that there's a compareTo() method. Try this:
System.out.println(PinSize.BIG.compareTo(PinSize.BIGGER));
The compareTo() method will return an int that is smaller than, equal to, or bigger than 0, depending on which value is "bigger". In the case of enum values, the "size" depends on the order of the enum value definitions.
The answers provided explain the problem well, but I would like to add my insights, because I feel that they don't answer question "why can't compare with < or >"?. The problem comes down to comparing references. PinSize.BIGGEST and PinSize.BIGGERER are reference variables. The same as the below:
String s;
int[] array;
MyObject myObject;
They represent addresses in memory. What is more, enums are singletons so there is always one object of the specified kind. Because of that the below line is allowed and returns true.
System.out.println(PinSize.BIG == PinSize.BIG); //true
Trying to check if one address in memory is greater or smaller than the other address in memory is impossible. Implementing Comparable interface and compareTo() method gives a chance to provide your own custom way of comparing objects not addresses in memory.
System.out.println(PinSize.BIG > PinSize.BIGGERER); // not possible
Related
I am learning about arrays, and basically I have an array that collects a last name, first name, and score.
I need to write a compareTo method that will compare the last name and then the first name so the list could be sorted alphabetically starting with the last names, and then if two people have the same last name then it will sort the first name.
I'm confused, because all of the information in my book is comparing numbers, not objects and Strings.
Here is what I have coded so far. I know it's wrong but it at least explains what I think I'm doing:
public int compare(Object obj) // creating a method to compare
{
Student s = (Student) obj; // creating a student object
// I guess here I'm telling it to compare the last names?
int studentCompare = this.lastName.compareTo(s.getLastName());
if (studentCompare != 0)
return studentCompare;
else
{
if (this.getLastName() < s.getLastName())
return - 1;
if (this.getLastName() > s.getLastName())
return 1;
}
return 0;
}
I know the < and > symbols are wrong, but like I said my book only shows you how to use the compareTo.
This is the right way to compare strings:
int studentCompare = this.lastName.compareTo(s.getLastName());
This won't even compile:
if (this.getLastName() < s.getLastName())
Use
if (this.getLastName().compareTo(s.getLastName()) < 0) instead.
So to compare fist/last name order you need:
int d = getFirstName().compareTo(s.getFirstName());
if (d == 0)
d = getLastName().compareTo(s.getLastName());
return d;
The compareTo method is described as follows:
Compares this object with the specified object for order. Returns a
negative integer, zero, or a positive integer as this object is less
than, equal to, or greater than the specified object.
Let's say we would like to compare Jedis by their age:
class Jedi implements Comparable<Jedi> {
private final String name;
private final int age;
//...
}
Then if our Jedi is older than the provided one, you must return a positive, if they are the same age, you return 0, and if our Jedi is younger you return a negative.
public int compareTo(Jedi jedi){
return this.age > jedi.age ? 1 : this.age < jedi.age ? -1 : 0;
}
By implementing the compareTo method (coming from the Comparable interface) your are defining what is called a natural order. All sorting methods in JDK will use this ordering by default.
There are ocassions in which you may want to base your comparision in other objects, and not on a primitive type. For instance, copare Jedis based on their names. In this case, if the objects being compared already implement Comparable then you can do the comparison using its compareTo method.
public int compareTo(Jedi jedi){
return this.name.compareTo(jedi.getName());
}
It would be simpler in this case.
Now, if you inted to use both name and age as the comparison criteria then you have to decide your oder of comparison, what has precedence. For instance, if two Jedis are named the same, then you can use their age to decide which goes first and which goes second.
public int compareTo(Jedi jedi){
int result = this.name.compareTo(jedi.getName());
if(result == 0){
result = this.age > jedi.age ? 1 : this.age < jedi.age ? -1 : 0;
}
return result;
}
If you had an array of Jedis
Jedi[] jediAcademy = {new Jedi("Obiwan",80), new Jedi("Anakin", 30), ..}
All you have to do is to ask to the class java.util.Arrays to use its sort method.
Arrays.sort(jediAcademy);
This Arrays.sort method will use your compareTo method to sort the objects one by one.
Listen to #milkplusvellocet, I'd recommend you to implement the Comparable interface to your class as well.
Just contributing to the answers of others:
String.compareTo() will tell you how different a string is from another.
e.g. System.out.println( "Test".compareTo("Tesu") ); will print -1
and System.out.println( "Test".compareTo("Tesa") ); will print 19
and nerdy and geeky one-line solution to this task would be:
return this.lastName.equals(s.getLastName()) ? this.lastName.compareTo(s.getLastName()) : this.firstName.compareTo(s.getFirstName());
Explanation:
this.lastName.equals(s.getLastName()) checks whether lastnames are the same or not
this.lastName.compareTo(s.getLastName()) if yes, then returns comparison of last name.
this.firstName.compareTo(s.getFirstName()) if not, returns the comparison of first name.
You're almost all the way there.
Your first few lines, comparing the last name, are right on track. The compareTo() method on string will return a negative number for a string in alphabetical order before, and a positive number for one in alphabetical order after.
Now, you just need to do the same thing for your first name and score.
In other words, if Last Name 1 == Last Name 2, go on a check your first name next. If the first name is the same, check your score next. (Think about nesting your if/then blocks.)
Consider using the Comparator interface described here which uses generics so you can avoid casting Object to Student.
As Eugene Retunsky said, your first part is the correct way to compare Strings. Also if the lastNames are equal I think you meant to compare firstNames, in which case just use compareTo in the same way.
if (s.compareTo(t) > 0) will compare string s to string t and return the int value you want.
public int Compare(Object obj) // creating a method to compare {
Student s = (Student) obj; //creating a student object
// compare last names
return this.lastName.compareTo(s.getLastName());
}
Now just test for a positive negative return from the method as you would have normally.
Cheers
A String is an object in Java.
you could compare like so,
if(this.lastName.compareTo(s.getLastName() == 0)//last names are the same
I wouldn't have an Object type parameter, no point in casting it to Student if we know it will always be type Student.
As for an explanation, "result == 0" will only occur when the last names are identical, at which point we compare the first names and return that value instead.
public int Compare(Object obj)
{
Student student = (Student) obj;
int result = this.getLastName().compareTo( student.getLastName() );
if ( result == 0 )
{
result = this.getFirstName().compareTo( student.getFirstName() );
}
return result;
}
If you using compare To method of the Comparable interface in any class.
This can be used to arrange the string in Lexicographically.
public class Student() implements Comparable<Student>{
public int compareTo(Object obj){
if(this==obj){
return 0;
}
if(obj!=null){
String objName = ((Student)obj).getName();
return this.name.comapreTo.(objName);
}
}
I'm trying to understand the theory behind the Comparator interface in Java. In particular, I need help understanding how the return value of the compare() method determines what goes on the top of the list.
Java Code
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/*
LOWER VALS. ARE AT TOP OF LIST
*/
class IncreasedComparison implements Comparator<Integer>{
#Override
public int compare(Integer first, Integer second) {
int value = first - second;
return value;
}
}
/*
HIGHER VALS. ARE AT TOP OF LIST
*/
class DecreasedComparison implements Comparator<Integer>{
#Override
public int compare(Integer first, Integer second){
int value = second - first;
return value;
}
}
public class ComparisonExample {
public static void main(String[] args) {
TreeMap<Integer,String> testOne = new TreeMap<>(new IncreasedComparison());
TreeMap<Integer,String> testTwo = new TreeMap<>(new DecreasedComparison());
testOne.put(1, "First Entry");
testOne.put(2, "Second Entry");
testOne.put(3, "Third Entry");
testOne.put(4, "Fourth Entry");
testOne.put(5, "Fifth Entry");
testTwo.put(1, "First Entry");
testTwo.put(2, "Second Entry");
testTwo.put(3, "Third Entry");
testTwo.put(4, "Fourth Entry");
testTwo.put(5, "Fifth Entry");
Set<Map.Entry<Integer,String>> firstOutput = testOne.entrySet();
Set<Map.Entry<Integer,String>> secondOutput = testTwo.entrySet();
for(Map.Entry<Integer,String> first : firstOutput){
System.out.println(first.getKey() + " " + first.getValue());
}
System.out.println("\n\n");
for(Map.Entry<Integer,String> second : secondOutput){
System.out.println(second.getKey() + " " + second.getValue());
}
}
}
Output
1 First Entry
2 Second Entry
3 Third Entry
4 Fourth Entry
5 Fifth Entry
5 Fifth Entry
4 Fourth Entry
3 Third Entry
2 Second Entry
1 First Entry
Discussion
Looking at the IncreasedComparison class, when the compare method returns a negative value, it means that the lower Keys (and respective elements) are at the top of the list. Then looking at the DecreasedComparison class, when the compare method returns a positive value, the higher Keys (and respective elements) are at the top of the list.
Why does this happen? Where does it occur in which the difference in the Key values can dictate whether the TreeList element is at the top of the list in one case, but then it can be at the bottom in the next?
Does this occur when the object implementing the Comparator interface is passed into the TreeMap constructor? By putting it into the constructor, does it set the precedent within the TreeMap that the negative return value of the compare() method means that smaller Integer values should be at the top of the list and vice versa for positive return values of the compare() method?
A Comparator (a <=> b) works like this,
-1 a comes before b, generally called less than
0 a equals b
1 a comes after b, generally called greater than
The Javadoc says (in part)
Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
And, yes. The TreeMap(Comparator) constructor Javadoc says
Constructs a new, empty tree map, ordered according to the given comparator. All keys inserted into the map must be mutually comparable by the given comparator
What the results mean
One way of thinking about the results of java.util.Comparator.compareTo is the following. Let
a ? b
Where ? can be = or > or <. Then let's add a zero to the equation
a ? b + 0
Then some algebra to move the ? to another position
a - b ? 0
If we try to put the different possible values for ? based on the values of a and b we have the following three combinations
if (a > b) then (a - b > 0)
if (a < b) then (a - b < 0)
if (a = b) then (a - b == 0)
That's where you get positive, negative and zero valued integer results.
Why go through those results?
For integers, the compareTo logic will be a bit dumb founded since you can easily just say a > b but for other non-simple types such as String this makes more sense.
Imagine a world without a a compareTo method. This would mean we would have to implement at least two methods to do comparison: a isGreaterThan and an equals method. Just those two would be enough because less than would be
!isGreaterThan(x) && !equals(x)
However, having all of that would involve many more method calls when a compareTo would save a lot more calls in the long run.
First of all, comparators have a contract: when they receive two values a and b, they will signify that a comes before b by returning a negative value, that b comes before a by returning a positive one, and that they should be considered of equal rank by returning a zero.
TreeMap in particular stores its comparator for future reference, and asks it several times for its opinion each time you access something in the TreeMap. To see exactly what happens and when, consider adding System.out.println(first, second) at the top of the compare function.
I read that the rule for the return value of these methods is that for obj1.compareTo(obj2) for example, if obj2 is under obj1 in the hierarchy, the return value is negative and if it's on top of obj1, then it's positive (and if it's equal then it's 0). However, in my class I saw examples where Math.signum was used in order to get -1 (for negative) and 1 (for positive) in the compareTo method.
Is there any reason for that?
EDIT:
Here is the code I meant:
Comparator comp = new Comparator() {
public int compare(Object obj1, Object obj2) {
Book book1 = (Book) obj1;
Book book2 = (Book) obj2;
int order = book1.getAuthor().compareTo(book2.getAuthor());
if (order == 0) {
order = (int) Math.signum(book1.getPrice() - book2.getPrice());
}
return order;
};
Is there any reason for using Math.signum
Yes there is.
order = (int) Math.signum(book1.getPrice() - book2.getPrice());
Suppose you have replace the above line with this
order = (int)(book1.getPrice() - book2.getPrice());
Now let us assume
book1.getPrice() returns 10.50
book2.getPrice() returns 10.40
If you do not use signum you will never have any compile time or run time error but value of order will be 0. This implies that book1 is equals to book2 which is logically false.
But if you use signum value of order will be 1 which implies book1 > book2.
But it must be mentioned that you should never make any assumption about compare function returning value between 1 and -1.
You can read official document for comparator http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html.
Any negative number will do to show that a < b. And any positive number will show that a > b. -1 and 1 serve that purpose just fine. There's no sense of being "more less than" or "more greater than"; they are binary attributes. The reason that any negative (or positive) value is permitted is probably historical; for integers it's common to implement the comparator by simple subtraction.
No.
PS: Frequent error in implementation is to use subtraction
public int compareTo(Object o) {
OurClass other = (OurClass)o; //Skip type check
return this.intField - other.intField;
}
It is wrong because if you call new OurClass(Integer.MIN_VALUE).compareTo(new OurClass(Integer.MAX_VALUE)) you get overflow. Probably Math.abs is attempt (failed) to deal with this problem.
The only reason I can see is that if you want to compare two ints for example (a and b), and you write
return a - b;
it might overflow. If you convert them to doubles and use (int)Math.signum( (double)a - (double)b ), you will definitely avoid that. But there are simpler ways of achieving the same effect, Integer.compare( a, b) for example.
I want to know why we cant use the <, <=, > or >= relational operators on Strings.
import java.util.*;
public class Coffee{
public static void main(String args[]){
String s1="Cat";
String s2="Dog";
System.out.println(s1 < s2);
}
}
gives the error "operator < cannot be applied to java.lang.String".
Why can't Java compare strings like this: C < D?
The simple answer is: because they weren't implemented. Java (unlike e.g. C/C++) does not rely on operator overloading, so you have to get the value of a String with length method and then compare the results with your < > <= >= operators.
Side note: Strings in Java also implement Comparable interface. It allows you to use compareTo method, which returns 0 if the argument is a strings are equal, a value less than 0 if the argument is greater than string which you run this method on; and a value greater than 0 if the argument is a string smaller than this string.
Side note 2: By "greater string" I mean lexicographically greater (alphabetically).
String is not a primitive data type like int and double are. Strings are objects.
For Strings, the relational operator, ==, only checks to see if the objects "point" to the same data in the heap.
For example,
String s1="Cat";
String s2= new String("Cat");
if(s1==s2)
System.out.println("They are the same");
The if statement WILL NOT execute.
This is because after you created an instance of "Cat", you create another instance of "Cat," in the heap. The two variables do not "point" to the same data.
compareTo methods check to see if the actual data that the variables are allocated to in a heap are equal to each other, and is one of the many correct ways to see if two String objects are equal to each other.
I hope it helped, if my response is unclear, please do not hesitate to ask.
If you really want to do this, use the compareTo result.
if ("a".compareTo("b") >= 0) {
// do stuff
}
If you want to ignore case you can do:
if (String.CASE_INSENSITIVE_ORDER.compare("A", "b") <= 0) {
// do stuff
}
Here's the right way:
import java.util.*;
public class Coffee {
public static void main(String args[]) {
String s1="Cat";
String s2="Dog";
System.out.println(s1.compareTo(s2));
}
}
When testing for equality of String's in Java I have always used equals() because to me this seems to be the most natural method for it. After all, its name already says what it is intended to do. However, a colleague of mine recently told me had been taught to use compareTo() == 0 instead of equals(). This feels unnatural (as compareTo() is meant to provide an ordering and not compare for equality) and even somewhat dangerous (because compareTo() == 0 does not necessarily imply equality in all cases, even though I know it does for String's) to me.
He did not know why he was taught to use compareTo() instead of equals() for String's, and I could also not find any reason why. Is this really a matter of personal taste, or is there any real reason for either method?
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.
The 2 main differences are that:
equals will take any Object as a parameter, but compareTo will only take Strings.
equals only tells you whether they're equal or not, but compareTo gives information on how the Strings compare lexicographically.
I took a look at the String class code, and the algorithm within compareTo and equals looks basically the same. I believe his opinion was just a matter of taste, and I agree with you -- if all you need to know is the equality of the Strings and not which one comes first lexicographically, then I would use equals.
When comparing for equality you should use equals(), because it expresses your intent in a clear way.
compareTo() has the additional drawback that it only works on objects that implement the Comparable interface.
This applies in general, not only for Strings.
compareTo has do do more work if the strings have different lengths. equals can just return false, while compareTo must always examine enough characters to find the sorting order.
In String Context:
compareTo: Compares two strings lexicographically.
equals: Compares this string to the specified object.
compareTo compares two strings by their characters (at same index) and returns an integer (positive or negative) accordingly.
String s1 = "ab";
String s2 = "ab";
String s3 = "qb";
s1.compareTo(s2); // is 0
s1.compareTo(s3); // is -16
s3.compareTo(s1); // is 16
compareTo() not only applies to Strings but also any other object because compareTo<T> takes a generic argument T. String is one of the classes that has implemented the compareTo() method by implementing the Comparable interface.(compareTo() is a method fo the comparable Interface). So any class is free to implement the Comparable interface.
But compareTo() gives the ordering of objects, used typically in sorting objects in ascending or descending order while equals() will only talk about the equality and say whether they are equal or not.
equals() can be more efficient then compareTo().
A very important difference between compareTo and equals:
"myString".compareTo(null); //Throws java.lang.NullPointerException
"myString".equals(null); //Returns false
equals() checks if two objects are the same or not and returns a boolean.
compareTo() (from interface Comparable) returns an integer. It checks which of the two objects is "less than", "equal to" or "greater than" the other. Not all objects can be logically ordered, so a compareTo() method doesn't always make sense.
Note that equals() doesn't define the ordering between objects, which compareTo() does.
Now I advise you to review the source code of both methods to conclude that equals is preferable over compareTo that involves some Math calculations.
It appears that both methods pretty much do the same thing, but the compareTo() method takes in a String, not an Object, and adds some extra functionality on top of the normal equals() method. If all you care about is equality, then the equals() method is the best choice, simply because it makes more sense to the next programmer that takes a look at your code. The time difference between the two different functions shouldn't matter unless you're looping over some huge amount of items. The compareTo() is really useful when you need to know the order of Strings in a collection or when you need to know the difference in length between strings that start with the same sequence of characters.
source: http://java.sun.com/javase/6/docs/api/java/lang/String.html
equals() should be the method of choice in the case of the OP.
Looking at the implementation of equals() and compareTo() in java.lang.String on grepcode, we can easily see that equals is better if we are just concerned with the equality of two Strings:
equals():
1012 public boolean equals(Object anObject) {1013 if (this == anObject) {1014 return true;1015 }1016 if (anObject instanceof String) {1017 String anotherString = (String)anObject;1018 int n = count;1019 if (n == anotherString.count) {1020 char v1[] = value;1021 char v2[] = anotherString.value;1022 int i = offset;1023 int j = anotherString.offset;1024 while (n-- != 0) {1025 if (v1[i++] != v2[j++])1026 return false;1027 }1028 return true;1029 }1030 }1031 return false;1032 }
and compareTo():
1174 public int compareTo(String anotherString) {1175 int len1 = count;1176 int len2 = anotherString.count;1177 int n = Math.min(len1, len2);1178 char v1[] = value;1179 char v2[] = anotherString.value;1180 int i = offset;1181 int j = anotherString.offset;1183 if (i == j) {1184 int k = i;1185 int lim = n + i;1186 while (k < lim) {1187 char c1 = v1[k];1188 char c2 = v2[k];1189 if (c1 != c2) {1190 return c1 - c2;1191 }1192 k++;1193 }1194 } else {1195 while (n-- != 0) {1196 char c1 = v1[i++];1197 char c2 = v2[j++];1198 if (c1 != c2) {1199 return c1 - c2;1200 }1201 }1202 }1203 return len1 - len2;1204 }
When one of the strings is a prefix of another, the performance of compareTo() is worse as it still needs to determine the lexicographical ordering while equals() won't worry any more and return false immediately.
In my opinion, we should use these two as they were intended:
equals() to check for equality, and
compareTo() to find the lexical ordering.
equals() checks whether two strings are equal or not.It gives boolean value.
compareTo() checks whether string object is equal to,greater or smaller to the other string object.It gives result as :
1 if string object is greater
0 if both are equal
-1 if string is smaller than other string
eq:
String a = "Amit";
String b = "Sumit";
String c = new String("Amit");
System.out.println(a.equals(c));//true
System.out.println(a.compareTo(c)); //0
System.out.println(a.compareTo(b)); //1
There are certain things which you need to keep in mind while overriding compareTo in Java e.g. Compareto must be consistent with equals and subtraction should not be used for comparing integer fields as they can overflow. check Things to remember while overriding Comparator in Java for details.
equals can take any Object as a parameter but compareTo can only take String.
when cometo null,compareTo will throw a exception
when you want to know where the diff happen,you can use compareTo.
This is an experiment in necromancy :-)
Most answers compare performance and API differences. They miss the fundamental point that the two operations simply have different semantics.
Your intuition is correct. x.equals(y) is not interchangeable with x.compareTo(y) == 0.
The first compares identity, while the other compares the notion of 'size'. It is true that in many cases, especially with primitive types, these two co-align.
The general case is this:
If x and y are identical, they share the same 'size': if x.equals(y) is true => x.compareTo(y) is 0.
However, if x and y share the same size, it does not mean they are identical.
if x.compareTo(y) is 0 does not necessarily mean x.equals(y) is true.
A compelling example where identity differs from size would be complex numbers. Assume that the comparison is done by their absolute value. So given two complex numbers: Z1 = a1 + b1*i and Z2 = a2 + b2*i:
Z1.equals(z2) returns true if and only if a1 = a2 and b1 = b2.
However Z1.compareTo(Z2) returns 0 for and infinite number of (a1,b1) and (a2,b2) pairs as long as they satisfy the condition a1^2 + b1^2 == a2^2 + b2^2.
Equals can be more efficient then compareTo.
If the length of the character sequences in String doesn't match there is no way the Strings are equal so rejection can be much faster.
Moreover if it is same object (identity equality rather then logical equality), it will also be more efficient.
If they also implemented hashCode caching it could be even faster to reject non-equals in case their hashCode's doesn't match.
String.equals() requires invoking instanceof operator while compareTo() requires not. My colleague has noted large performance drop-down caused by excessive numbers of instanceof calls in equals() method, however my test has proved compareTo() to be only slightly faster.
I was using, however, Java 1.6. On other versions (or other JDK vendors) the difference could be larger.
The test compared each-to-each string in 1000 element arrays, repeated 10 times.
String s1 = "a";
String s2 = "c";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));
This prints -2 and false
String s1 = "c";
String s2 = "a";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));
This prints 2 and false
String s1 = "c";
String s2 = "c";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));
This prints 0 and true
equals returns boolean if and only if both strings match.
compareTo is meant to not just tell if they match but also to tell which String is lesser than the other, and also by how much, lexicographically. This is mostly used while sorting in collection.
Equals -
1- Override the GetHashCode method to allow a type to work correctly in a hash table.
2- Do not throw an exception in the implementation of an Equals method. Instead, return false for a null argument.
3-
x.Equals(x) returns true.
x.Equals(y) returns the same value as y.Equals(x).
(x.Equals(y) && y.Equals(z)) returns true if and only if x.Equals(z) returns true.
Successive invocations of x.Equals(y) return the same value as long as the object referenced by x and y are not modified.
x.Equals(null) returns false.
4- For some kinds of objects, it is desirable to have Equals test for value equality instead of referential equality. Such implementations of Equals return true if the two objects have the same value, even if they are not the same instance.
For Example -
Object obj1 = new Object();
Object obj2 = new Object();
Console.WriteLine(obj1.Equals(obj2));
obj1 = obj2;
Console.WriteLine(obj1.Equals(obj2));
Output :-
False
True
while compareTo -
Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
It returns -
Less than zero - This instance precedes obj in the sort order. Zero - This instance occurs in the same position in the sort order as obj. Greater than zero - This instance follows obj in the sort order.
It can throw ArgumentException if object is not the same type as instance.
For example you can visit here.
So I suggest better to use Equals in place of compareTo.
equals:
required for checking equality and restricting duplicates. Many classes of Java Library use this in case they wanted to find duplicates. e.g. HashSet.add(ob1) will only add if that doesn't exist. So if you are extending some classes like this then override equals().
compareTo:
required for ordering of element. Again for stable sorting you require equality, so there is a return 0.
"equals" compare objects and return true or false and
"compare to" return 0 if is true or an number [> 0] or [< 0] if is false
here an example:
<!-- language: lang-java -->
//Objects Integer
Integer num1 = 1;
Integer num2 = 1;
//equal
System.out.println(num1.equals(num2));
System.out.println(num1.compareTo(num2));
//New Value
num2 = 3;//set value
//diferent
System.out.println(num1.equals(num2));
System.out.println(num1.compareTo(num2));
Results:
num1.equals(num2) =true
num1.compareTo(num2) =0
num1.equals(num2) =false
num1.compareTo(num2) =-1
Documentation Compare to: https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html
Documentation Equals : https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)
Here one thing is important while using compareTo() over equals() that compareTo works for the classes that implements 'Comparable' interface otherwise it will throw a NullPointerException. String classes implements Comparable interface while StringBuffer does not hence you can use "foo".compareTo("doo") in String object but not in StringBuffer Object.
I believe equals and equalsIgnoreCase methods of String return true and false which is useful if you wanted to compare the values of the string object, But in case of implementing compareTo and compareToIgnoreCase methods returns positive, negative and zero value which will be useful in case of sorting.