Comparing StringBuffer content with equals
Clash Royale CLAN TAG#URR8PPP
Comparing StringBuffer content with equals
StringBuffer sb1 = new StringBuffer("Java");
StringBuffer sb2 = new StringBuffer("Java");
System.out.println(sb1 == sb2);
System.out.println(sb1.equals(sb2));
Here both are returning false. How is it possible?
9 Answers
9
The equals
method of StringBuffer
is not overridden from Object
, so it is just reference equality, i.e., the same as using ==
. I suspect the reason for this is that StringBuffer
is modifiable, and overriding equals
is mostly useful for value-like classes that you might want to use as keys (though lists also have an overridden equals
and StringBuffer
is kind of a list, so this is a bit inconsistent).
equals
StringBuffer
Object
==
StringBuffer
equals
equals
StringBuffer
sb1.equals(sb2)
sb1.toString().equals(sb2.toString())
hashCode()
You are comparing the references to the StringBuffer objects rather than the actual strings within the StringBuffer.
System.out.println(sb1.toString().equals(sb2.toString()))
would return true and I assume this is what you had expected or wanted to achieve.
System.out.println(sb1.toString().equals(sb2.toString()))
1. System.out.println(sb1 == sb2);
StringBuffer's equals method returns true only when a StringBuffer object is compared with itself. It returns false when compared with any other StringBuffer, even if the two contain the same characters.
This is because "==" checks the reference equality and since both sb1 and sb2 are different object references, so the output in this case is "false"
Still if you want to check if the content is equal in these two StringBuffer Objects, you can use this:
sb1.toString().equals(sb2.toString())
2. System.out.println(sb1.equals(sb2));
This is giving output as "false" because .equals() method has not been overridden in the StringBuffer Class. So it is using the .equals() method from its parent "Object" class. In the object class .equals() has been written to check the reference equality.
Note that sb3.equals(sb4) will return "true" in case of String. Because .equals() method has been overridden in String class to check and match the content of two different Strings.
The simple answer is that StringBuffer (and StringBuilder) do not redefine the base semantics of Object.equals(). So equals
on a StringBuffer will simply compare object references.
equals
In fact, String, StringBuffer, StringBuilder and CharBuffer all implement the CharSequence interface, and the javadoc for this interface says this:
This interface does not refine the general contracts of the equals and hashCode methods. The result of comparing two objects that implement CharSequence is therefore, in general, undefined. Each object may be implemented by a different class, and there is no guarantee that each class will be capable of testing its instances for equality with those of the other. It is therefore inappropriate to use arbitrary CharSequence instances as elements in a set or as keys in a map.
StringBuffer
seems to have no equals
method of its own, so my first guess would be that StringBuffer
inherits the equals
method of Object
, which compares using sb1 == sb2
. Therefore, both methods yield the same result.
StringBuffer
equals
StringBuffer
equals
Object
sb1 == sb2
both compares two references to objects (sb1 is one, and sb2 is second), thus both are different.
If You are trying to compare content - use method compareTo(...) in String class - that is - first get String content of StringBuffer using method toString() (.toString().compareTo).
Ps. as of JDK 5, there is another much faster class that behaves exactly as StringBuffer - it is StringBuilder, and is also but is not thread safe.
StringBuffer sb1 = new StringBuffer("Java");
StringBuffer sb2 = new StringBuffer("Java");
System.out.println(sb1.toString().compareTo(sb2.toString()));
StringBuidler is not threadsafe as far as I know
– Yaneeve
Jan 6 '10 at 11:18
StringBuilder is not thread safe. From the SDK docs on StringBuilder: "compatible with StringBuffer, but with no guarantee of synchronization ", from the introduction paragraph here: java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuilder.html
– David Rodríguez - dribeas
Jan 6 '10 at 11:26
of course, my bad. read the doc of StringBuffer too quick, IT is suplemented by StringBuilder, thus it is meant for use by a single thread. sorry for that.
– mkolodziejski
Jan 6 '10 at 11:32
The fact is that it is faster because it removes the thread safety requirement from StringBuffer
– David Rodríguez - dribeas
Jan 6 '10 at 11:45
Since JDK 1.6, lock elision makes the difference between
StringBuffer
and StringBuilder
negligible. However, I don't know the details, maybe lock elision is not able to catch more complex use cases, so it's always better to use StringBuilder, if you don't need thread safety.– Oliv
Jul 27 '16 at 6:47
StringBuffer
StringBuilder
Wondering why StringBuffer
does not override the equals
method. Probably because the content of the object is obtained by the toString()
method and which has the desired method.
StringBuffer
equals
toString()
With JDK/11, one can now compare two StringBuffer
s without an additional toString
, this can be done using the newly introduced API -
StringBuffer
toString
public int compareTo(StringBuffer another)
Compares two StringBuffer
instances lexicographically. This method
follows the same rules for lexicographical comparison as defined in
the CharSequence.compare(this, another)
method.
For finer-grained, locale-sensitive String comparison, refer to Collator.
StringBuffer
CharSequence.compare(this, another)
Implementation Note: This method synchronizes on this, the current
object, but not StringBuffer another with which this StringBuffer is
compared.
Returns: the value 0 if this StringBuffer contains the same character
sequence as that of the argument StringBuffer; a negative integer if
this StringBuffer is lexicographically less than the StringBuffer
argument; or a positive integer if this StringBuffer is
lexicographically greater than the StringBuffer argument.
Sample usage :
StringBuffer stringBuffer = new StringBuffer("null");
StringBuffer anotherStringBuffer = new StringBuffer("NULL");
System.out.println(stringBuffer.compareTo(anotherStringBuffer) == 0); // shall print 'false'
Posting this answer, since most of the questions pertaining to comparing the StringBuffer ends up here.
– nullpointer
Aug 10 at 13:44
Stringbuffer's equals()
is not overridden. It does not compare values, it only compares reference value assignments. That is why you are getting false as they both are referring to different objects.
equals()
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
As I just fell into the same pit, I'd like to remark that this is simply a stupid design decision: Instead of
sb1.equals(sb2)
I'll have to writesb1.toString().equals(sb2.toString())
(because this is what actually matters). Maybe it's also the reason: Besides the current contents, there are internal attributes (like buffer capacity) which may or may not affect the view of equality. Finally:hashCode()
has the same problem.– U. Windl
May 28 at 9:03