• Post Reply Bookmark Topic Watch Topic
  • New Topic

Compare two StringBuffer objects  RSS feed

 
C Law
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I searched the forum briefly and didn't find a similar post.

StringBuffer a = new StringBuffer("ABC");
StringBuffer b = new StringBuffer("ABC");
System.out.println(a.equals(b));

Why the output is false? Seems the content of a StringBuffer
object involves more about the string inside.

Thanks.
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The StringBuffer class does not override the equals method so it uses the equals method of Object.

If a and b are two objects from a class which doesn't override equals, then

a.equals(b) is the same as a == b
 
Jerret Halter
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It is because StringBuffer does not override the equals(Object o) method from Object. Object's equals(Object b) method looks like this:



So since you created two differnt StringBuffer objects that are not refering to the same thing they will not be equal using equal(Object o).
 
marc weber
Sheriff
Posts: 11343
Java Mac Safari
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you check the API documentation, you will see that StringBuffer does not override the equals method. So equals behaves with the simple implementation inherited from Object.

Consider that a StringBuffer (or StringBuilder) is for "assembling" Strings. The StringBuffer might be considered a work in progress, and the resulting String (from calling toString) is the final product.

So to compare StringBuffer "contents," you can convert to String and use equals...

String s1 = myBuffer1.toString();
String s2 = myBuffer2.toString();
boolean equalBuffers = s1.equals(s2);
 
C Law
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks to all of you!
 
ak pillai
author
Ranch Hand
Posts: 288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you look at the JAVA API


The StringBuffer extends Object not String and also only overrides toString() method from the Object. equals() and hashCode() it uses the default one in Object class. So as suggested before, The Object class compares only the references with == operator. That is why, it returns false. convert to String using toString() and compare for equality.
 
Ernest Friedman-Hill
author and iconoclast
Sheriff
Posts: 24217
38
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not only that, but StringBuffer doesn't override equals(). It says so in the API.
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
LOL
 
Jerret Halter
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jerret Halter:
It is because StringBuffer does not override the equals(Object o) method from Object. Object's equals(Object b) method looks like this:



So since you created two differnt StringBuffer objects that are not refering to the same thing they will not be equal using equal(Object o).
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah, thanks for pointing that out. I almost overlooked that earlier.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Notice that calling toString() on a StringBuffer has some performance implications: the newly created String object shares the character array with the StringBuffer, so when you subsequently change the content of the StringBuffer (other than just appending something to it), the StringBuffer needs to make a copy of the array.

With other words, having to call toString() on a StringBuffer can in some situations negate the performance advantage of using a StringBuffer in the first place.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hurm, since this is in Beginner I'll note that beginners may want to just skip this post. But in response to Ilja:

As of JDK 5 String and StringBuffer no longer share a backing array. Which means the copying occurs every time you call toString() - which is actually less efficient, but gives more predictable behavior and may prevent some subtle bugs.

And for the original poster:

Most of the time when people use StringBuffers, they only convert toString() once, when they're otherwise done changing the content of the StringBuffer. At this point, there's no reason to keep the StringBuffer around anymore... and no reason to call equals() on the StringBuffer; you can just use the String instead.

On the other hand, if a programmer wants to call equals() on a StringBuffer before they're done changing its contents - I think they may be asking for trouble. Because two StringBuffers may be "equal" (equal content) at one moment, but if you change their content, that may not be true later. So being "equal" is a temporary thing for StringBuffers, and I'm doubtful that it's really useful to test this, in most situations. (Which is probably why they never overrode equals() and hashCode() for StringBuffer.)

In other words: if you're done changing the content of your StringBuffer, just call toString() and discard the buffer. If you're not done - then why do you want to call equals() at all? What exactly is that going to be useful for? While there may be rare cases where this is useful, I think in most cases it's unnecessary or worse. So I would urge the programmer to consider whether they need to do this.
[ March 29, 2006: Message edited by: Jim Yingst ]
 
Ernest Friedman-Hill
author and iconoclast
Sheriff
Posts: 24217
38
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think some people -- perhaps those with past C programming experience -- want a mutable String in Java, and they expect StringBuffer to be it.

One additional point in favor of Jim's arguments: Java 5 has StringBuilder, which is basically a new, improved StringBuffer. It doesn't have equals() or hashCode() defined, either.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jim, thanks for the info on Java 5. And I agree with all of your points.
 
Tom Fulton
Ranch Hand
Posts: 96
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Since I'm relatively new here, I don't want to rock the boat too early. But this topic is one of my pet peeves about Java. Can anyone give me a good reason WHY StringBuffer (and, for that matter, StringBuilder) doesn't have an equals method defined? For the very reasons described here (the extra call to toString() needed), having to convert from a StringBuffer to a String in order to test for value equality has always seemed counterintuitive and stupid. Furthermore, StringBuffer has always been used as a mutable String (whether it should be or not), and it's just common sense (to me, anyway) that there be a direct way to test for value equality. So what's the reason?
 
Tony Morris
Ranch Hand
Posts: 1608
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Tom Fulton:
Since I'm relatively new here, I don't want to rock the boat too early. But this topic is one of my pet peeves about Java. Can anyone give me a good reason WHY StringBuffer (and, for that matter, StringBuilder) doesn't have an equals method defined? For the very reasons described here (the extra call to toString() needed), having to convert from a StringBuffer to a String in order to test for value equality has always seemed counterintuitive and stupid. Furthermore, StringBuffer has always been used as a mutable String (whether it should be or not), and it's just common sense (to me, anyway) that there be a direct way to test for value equality. So what's the reason?


I can give you the "left wing" answer. No type should override equals ever. Therefore, I choose to rephrase your question: "why do Java types override equals?" - the best answer is purely speculation, so let's avoid it.

The next obvious question is: "why?". I cannot answer that simply (both because I'm in a bit of a rush, and I suspect you don't want to hear it), however, I can refer you to an example of how to achieve it properly. Specifically, the Equalable interface of ContractualJ permits you to abstract the "equalness" (the strategy of determining equality) of any type (including StringBuffer) while AntiObject ensures that every type does not override the equals method.

The problem is that the collections API relies heavily on equals/hashCode, which means that by digressing away from this concept, you also disallow the use of collections. The quaity of collections aside (though relevant), this is why ContractualJ includes its own collections that have no dependence on Object methods. Though I admit that it is far from complete. Must run

http://contractualj.com/api/net/tmorris/adt/Equalable.html
http://contractualj.com/api/net/tmorris/AntiObject.html
 
Alan Moore
Ranch Hand
Posts: 262
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
String has several convenience methods for doing various comparisons like startsWith(), endsWith(), contentEquals(), etc. The most useful is regionMatches(), which is potentially the basis for all the others. Unfortunately, none of them are included in StringBuffer or StringBuilder, and even the ones in String usually only work other Strings (although some have been overloaded to accept StringBuffers or CharSequences). I created a static regionMatches() method, based on String's, that works with two CharSequences; it's been extremely useful. I've thought about submitting an RFE to have something like it included in the core classes, but I don't know where they could put it. Maybe in a CharSequences utility class? What would really be nice is if they could move all those convenience methods from String to the utility class, but that isn't going to happen.
 
Ken Blair
Ranch Hand
Posts: 1078
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Tom Fulton:
Since I'm relatively new here, I don't want to rock the boat too early. But this topic is one of my pet peeves about Java. Can anyone give me a good reason WHY StringBuffer (and, for that matter, StringBuilder) doesn't have an equals method defined? For the very reasons described here (the extra call to toString() needed), having to convert from a StringBuffer to a String in order to test for value equality has always seemed counterintuitive and stupid. Furthermore, StringBuffer has always been used as a mutable String (whether it should be or not), and it's just common sense (to me, anyway) that there be a direct way to test for value equality. So what's the reason?


Post count and registered dates ought not have any impact on what someone can put forth. I've never heard a great reason as to why they ought not have an equals() method. The typical argument is that they're mutable and it wouldn't make sense to compare the contents, yet that's exactly what AbstractList does and I frankly do not see the distinction. The API describes StringBuilder as a "Mutable sequence of characters" not as some temporary building block for String concatenation. That being said, I've honestly never had any reason to compare StringBu(ilder/ffer)s and haven't conceived of a reason why I would want to yet either. If it's really that big of deal make a convenience method to iterate over each.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!