Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Use toString().equals() vs. equals()

This is a question of theory. I have an object of my own design with a bunch of variables, methods, etc. I overrode the toString method, mostly for logging purposes, to return the value of the variables. It seems to me like the easiest and most straightforward way to compare instances of this object would be to compare what gets returned from the toString method. For example, the equals method might look like

public boolean equals(MyObject instance)
{
   return toString().equals(instance.toString());
}

Is there a reason not to do this?

like image 224
windedmoose Avatar asked Dec 25 '22 16:12

windedmoose


2 Answers

One reason to avoid this pattern would be speed: in order to compare for equality using toString(), you have to do this:

  • Create a temporary String object for the object this
  • Create a temporary String object for the object instance
  • Compare the first String to the second String character by character
  • Make temporary strings available for garbage detection

You can skip most of this if you do the comparison directly. For example, comparing ints directly takes comparing 4 bytes, while comparing their string representation takes up to nine byte comparisons. Similar situations happen with other data types.

like image 165
Sergey Kalinichenko Avatar answered Jan 05 '23 11:01

Sergey Kalinichenko


There are performance reasons not to do what you're asking which have been concisely summarized by dasblinkenlight.

Another important reason to avoid this pattern relates to the general contract for the toString() method. All of the overrideable methods of class Object have a general contract. Because these methods are inherited by every class you define in Java and because they are so commonly overridden in many custom classes, it is very important to know and adhere to their general contracts.

The general contract for toString() is the simplest of the Object methods:

Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.

There is no requirement that the string returned by toString() fit a particular format, nor is there a requirement that you must specify the format of the string returned as part of your API.

Because this is so, the string representation of the object that is returned by toString() is most commonly an implementation detail which is free to change from one version of your class to the next. Changing the string representation returned by toString() could cause program failures if you base equals comparisons on them.

Another reason not to base equals comparison on the toString() method is that doing so does not provide your class with the infrastructure required so that it may be used with the Java Collections Framework. Java Collections classes require well-formed equals() and hashCode() methods for the objects stored within them in order to work properly:

  • If there is any chance that the class you are writing will be used in any of the Java Collections Framework classes and/or that it may be used by another programmer, it is worth the price to write well-formed equals() and hashCode() methods.

  • Since the performance of any reasonably well-formed equals() method will exceed the performance of a toString()-based string comparison ... and since many classes should have a well-formed equals() method anyway ... you may as well just go ahead and use the custom equals() method.

like image 36
scottb Avatar answered Jan 05 '23 10:01

scottb