Comparing StringBuffer content with equals

The name of the pictureThe name of the pictureThe name of the pictureClash 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





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 write sb1.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



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 StringBuffers 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.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard