Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / October 2007

Tip: Looking for answers? Try searching our database.

Confused about StringBuilder equals

Thread view: 
sunstormrider@hotmail.com - 23 Oct 2007 19:14 GMT
Hi guys

OK - I have a pretty basic problem:

If I do

String a = "fred";
String b = "fred";

if (a.equals(b))
{ System.out.println("Equal"); }
else {System.our.println("Not equal"); }

then everything is as I'd expect - i.e. it returns Equal.

However, if I make my Strings StringBuilders, I'm getting a response
I'm not expecting:

StringBuilder a = new StringBuilder("fred");
StringBuilder b = new StringBuilder("fred");

if (a.equals(b))
{ System.out.println("Equal"); }
else {System.our.println("Not equal"); }

I'm getting Not equal.   I know StringBuilder inherits from Object but
I can't see how to get around this one with casting.   Can anyone help
please it's driving me nuts?

Cheers
Sun
Patricia Shanahan - 23 Oct 2007 19:23 GMT
...
> However, if I make my Strings StringBuilders, I'm getting a response
> I'm not expecting:

To find out what to expect from an API class method, read its documentation:

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuilder.html#toString()

A StringBuilder is equal to itself, and nothing else. Anything else
would be a bad idea, given the fact that StringBuilder is not only
mutable, it is positively designed for change.

> I'm getting Not equal.   I know StringBuilder inherits from Object
> but I can't see how to get around this one with casting.   Can anyone
> help please it's driving me nuts?

If you want to ask whether two StringBuilder instances currently contain
equal Strings:

a.toString().equals(b.toString())

However, remember this can change at any time. If you do not intend
changes, use String rather than StringBuilder.

Patricia
sunstormrider@hotmail.com - 23 Oct 2007 20:05 GMT
> sunstormri...@hotmail.com wrote:
>
[quoted text clipped - 24 lines]
>
> Patricia

Brilliant - thanks very much.   Of course - a StringBuilder is an
object, so it's the textual representations of each that I needed to
test - not the objects themselves.

Many many thanks

Sun
Thomas Kellerer - 23 Oct 2007 21:12 GMT
Patricia Shanahan wrote on 23.10.2007 20:23:
> A StringBuilder is equal to itself, and nothing else. Anything else
> would be a bad idea, given the fact that StringBuilder is not only
> mutable, it is positively designed for change.

There are classes in the JDK that are mutable and still implement a decent
equals() method (e.g.: Point, AbstractList, Date).

The only thing that equals() == true means, is that the two objects are equal at
that point in time when they are compared to each other.

The equals() contract does not guarantee that they will stay equal forever.

The documentation for equals() even takes mutable objects into account:

"for any non-null reference values x and y, multiple invocations of x.equals(y)
consistently return true  or consistently return false, provided no information
used in equals comparisons on the objects is modified."

So why shouldn't it be possible for StringBuilder to implement equals() based on
comparing all characters and thus avoiding the overhead of copying the char
array around just for comparing.
I would very much appreciate that and I don't see a problem with the fact that
it's mutable.

Thomas
Joshua Cranmer - 23 Oct 2007 21:53 GMT
> Patricia Shanahan wrote on 23.10.2007 20:23:
>> A StringBuilder is equal to itself, and nothing else. Anything else
[quoted text clipped - 3 lines]
> There are classes in the JDK that are mutable and still implement a
> decent equals() method (e.g.: Point, AbstractList, Date).

AFAIK, the classes that are mutable and have an actual comparative
equals() method fall into two categories:
1. Collections and related components.
2. Classes that are mutable by design mistake (e.g., Point, Date).

The second category should generally be assumed (except for defensive
purposes) to be used immutably, so the verity of equals /should/ remain
constant throughout all points of time, so they are an exception to the
rule that `mutability should generally not use equals.'

The first category has two use cases: highly ephemeral instances with
high mutability, and long-term backings for which changes are made only
sporadically. It is for the latter purpose where equals() comes in.

> So why shouldn't it be possible for StringBuilder to implement equals()
> based on comparing all characters and thus avoiding the overhead of
> copying the char array around just for comparing.
> I would very much appreciate that and I don't see a problem with the
> fact that it's mutable.

The problem with StringBuilder -- and any other class with similar usage
patterns -- is that it only exists for the small amount of time in which
it is constructing the final object. It is not only mutable, but it does
not really have a sense of an immutable state or use case. The equals()
method implies some sort of immutability which can generally be
supplied, but which is generally idiotic in the use case of
StringBuilder, since it shouldn't exist for long as a StringBuilder.

Signature

Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Patricia Shanahan - 23 Oct 2007 22:15 GMT
...
>> So why shouldn't it be possible for StringBuilder to implement
>> equals() based on comparing all characters and thus avoiding the
[quoted text clipped - 9 lines]
> supplied, but which is generally idiotic in the use case of
> StringBuilder, since it shouldn't exist for long as a StringBuilder.

And if you find yourself wanting to use a StringBuilder without
intending its value to change you have finished building, and should be
using the String it built.

Patricia
Roedy Green - 23 Oct 2007 20:30 GMT
>String a = "fred";
>String b = "fred";

And just when you thought you understood it all2,

boolean same = a == b;

same is true.
see http://mindprod.com/jgloss/gotchas.html#COMPARISON
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Lew - 23 Oct 2007 22:54 GMT
>> String a = "fred";
>> String b = "fred";
[quoted text clipped - 5 lines]
> same is true.
> see http://mindprod.com/jgloss/gotchas.html#COMPARISON

String c = new String( "fred" );

(a == c) will be false.

Signature

Lew

Mike  Schilling - 23 Oct 2007 23:30 GMT
>>String a = "fred";
>>String b = "fred";
[quoted text clipped - 4 lines]
>
> same is true.

Why shouldn't it be?  Both a and b point to the object "fred".

I would guess that

   Integer i = 0;
   Integert j = 0;

   boolean same = i == j;

also results in "true", though at the moment I'm too lazy to check.
Daniel Dyer - 23 Oct 2007 23:49 GMT
>>> String a = "fred";
>>> String b = "fred";
[quoted text clipped - 15 lines]
>
> also results in "true", though at the moment I'm too lazy to check.

It does, but this doesn't:

    Integer i = 128;
    Integer j = 128;

    boolean same = i == j;

One of the many joys of autoboxing.

Dan.

Signature

Daniel Dyer
http//www.uncommons.org

Lew - 24 Oct 2007 00:11 GMT
> It does, but this doesn't [evaluate to true]:
>
[quoted text clipped - 4 lines]
>
> One of the many joys of autoboxing.

Doesn't /necessarily/ evaluate to true.  Does autoboxing use valueOf()?

If so, it might return cached values that actually would evaluate to the same
object for the same primitive value.

Of course, the key word is "might".

Signature

Lew

Daniel Dyer - 24 Oct 2007 00:17 GMT
>> It does, but this doesn't [evaluate to true]:
>>      Integer i = 128;
[quoted text clipped - 8 lines]
>
> Of course, the key word is "might".

Yes, in practice 128 is not cached (at least by Sun's implementation), but  
the JLS does allow for it to be:

http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7

<jls>
If the value p being boxed is true, false, a byte, a char in the range  
\u0000 to \u007f, or an int or short number between -128 and 127, then let  
r1 and r2 be the results of any two boxing conversions of p. It is always  
the case that r1 == r2.

Discussion

Ideally, boxing a given primitive value p, would always yield an identical  
reference. In practice, this may not be feasible using existing  
implementation techniques. The rules above are a pragmatic compromise. The  
final clause above requires that certain common values always be boxed  
into indistinguishable objects. The implementation may cache these, lazily  
or eagerly.

For other values, this formulation disallows any assumptions about the  
identity of the boxed values on the programmer's part. This would allow  
(but not require) sharing of some or all of these references.
</jls>

Signature

Daniel Dyer
http//www.uncommons.org

Roedy Green - 24 Oct 2007 07:34 GMT
>     Integer i = 128;
>     Integer j = 128;
>
>     boolean same = i == j;

Surely there is no need for an unbox.

Does the boxing use valueOf to shortcut share Integers with low values
or does it create two different 128 objects?  

Some experiments are in order.
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Daniel Pitts - 24 Oct 2007 17:30 GMT
>>     Integer i = 128;
>>     Integer j = 128;
[quoted text clipped - 7 lines]
>
> Some experiments are in order.
I believe that Integer.valueOf will "intern" a certain range of values.
(possibly -128 to 127, but I don't know OTTOMH), The same is true about
the other primitive wrappers I believe.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Lew - 25 Oct 2007 01:04 GMT
>>>     Integer i = 128;
>>>     Integer j = 128;
[quoted text clipped - 9 lines]
> (possibly -128 to 127, but I don't know OTTOMH), The same is true about
> the other primitive wrappers I believe.

Daniel Dyer explained this fully in his post on this topic yesterday,
including a detailed citation from the JLS.

Signature

Lew

Daniel Pitts - 25 Oct 2007 03:20 GMT
>>>>     Integer i = 128;
>>>>     Integer j = 128;
[quoted text clipped - 12 lines]
> Daniel Dyer explained this fully in his post on this topic yesterday,
> including a detailed citation from the JLS.

Ah, must have missed that one.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.