StringBuilder

L

Lew

Wanja said:
(e-mail address removed) says...


And "still" is the keyword. The question remains: For how long will this
hold true?

You said "today's compilers".
So what's the problem with these? before answering, just have a look at
this:
http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html

That tells part of the story, but extra objects still cause both memory and time overhead. Time comes from GC cycles that kick in because you were profligate.
....[snip] ...
Nope, I'm arguing that:

String x="";
for(String s : strings){
x+=s;
}

or

String x="";
for(String s : strings){
x=x+s;
}

Is simple pattern that could be detected by tomorrows JIT-compilers and

But you changed your argument. You _were_ speaking of "today's compilers". Now suddenly you're speaking of "tomorrows [sic] JIT-compilers".

Besides shifting your ground, you have weakened your argument. It's one thing to program to allow "tomorrow's compilers" to further optimize your code, it's quite another to program to *require* "tomorrow's compilers" to further optimize your code.

You don't know for a fact that "tomorrow's compilers" will ever optimize across multiple lines of 'String' concatenation.

As you say, they "could be" able to do that; you just cannot aver that they will be able to do that.

But of course, that's only now that you've moved the discussion from "today's compilers" as you first said, to "tomorrow's compilers" as you now wish to discuss.
transformed into:

StringBuilder b = new StringBuilder();
for(String s : strings){
b.append(s);
}
String x = b.toString();

But I don't think any compiler programmer would care to detect this
pattern:

StringBuffer b = new StringBuffer ();
for(String s : strings){
b.append(s);
}
String x = b.toString();

Just to transform it into the the StringBuilder-variant.

That would likely be incorrect anyway, since the semantics differ. Of course, "tomorrow's JIT compiler" could figure out that there's no thread leak, so it "could be" able to do it. Maybe.
 
E

Eric Sosman

On 9/18/2011 1:44 AM, Peter Duniho wrote:

(Amusing aside: Thunderbird's spell-checker wants to change
Peter's last name to "Whodunit.")
[...]
StringBuilder composes its string in a char[]. Unfortunately it can't
simply plop that into a String object at the end. It has to allocate
yet another buffer, copy into it, and that becomes your string object.
[...]

Are you sure that's the implementation?

In .NET, there is also a String and StringBuilder class pair, and
StringBuilder.ToString() does in fact just create a new String instance
using the existing buffer.[...]

In any case, if Java does _not_ implement it that way, I suspect that's
out of a different decision-making process rather than ignorance. In
other words, they have already considered whether it's a worthwhile
optimization and decided otherwise. [...]

I don't have old Java source, but I do have an old O'Reilly
book ("Java In a Nutshell, 2nd Edition, Covers Java 1.1, by David
Flanagan") that states

The StringBuffer.toString() method does not copy the internal
array of characters; instead it shares that array with the
new String object, and makes a new copy for itself only when
further modifications are made to the StringBuffer object.

Assuming the author was correct, it follows that the implementation
changed at some later point. Presumably, that change was driven by
evidence that the "optimization" wasn't worth while.
 
J

Jan Burse

Eric said:
I don't have old Java source, but I do have an old O'Reilly
book ("Java In a Nutshell, 2nd Edition, Covers Java 1.1, by David
Flanagan") that states

The StringBuffer.toString() method does not copy the internal
array of characters; instead it shares that array with the
new String object, and makes a new copy for itself only when
further modifications are made to the StringBuffer object.

Assuming the author was correct, it follows that the implementation
changed at some later point. Presumably, that change was driven by
evidence that the "optimization" wasn't worth while.

I guess first of all probably a reengineering was done, and
StringBuffer was split into AbstractStringBuilder and StringBuffer.
And then StringBuilder was created. The class diagramm is basically:

AbstractStringBuilder
/ \
StringBuffer StringBuilder

Most of the StringBuffer methods are synchronized and then delegate
to the abstract super class. In StringBuilder the methods are
non-synchronized and then also delegate to the abstract super class.

The delegation instead of just using the methods from the abstract
class is needed so that the correct type is returned. For example
the AbstractStringBuilder does have an append that even returns
an AbstractStringBuilder. But it is then overridden by a method that
returns StringBuffer respectively StringBuilder.

So we see for example:

In StringBuffer:

public synchronized StringBuffer append(char c) {
super.append(c);
return this;
}

In StringBuilder:

public StringBuilder append(char c) {
super.append(c);
return this;
}

The necessary overriding capability called covariant return types is
only available since Java 1.5.

http://www.java-tips.org/java-se-tips/java.lang/covariant-return-types.html

So maybe during all this quality language reengineering the aspect
of optimization became less prominent.

Best Regards
 
E

Eric Sosman

I guess first of all probably a reengineering was done, and
StringBuffer was split into AbstractStringBuilder and StringBuffer.
And then StringBuilder was created. The class diagramm is basically:

AbstractStringBuilder
/ \
StringBuffer StringBuilder

I do not know whether buffer-sharing was dropped before, after,
or with the introduction of StringBuilder.
Most of the StringBuffer methods are synchronized and then delegate
to the abstract super class. In StringBuilder the methods are
non-synchronized and then also delegate to the abstract super class.

Some methods delegate, some do not. StringBuilder.toString()
in particular does not delegate to the superclass.
 
S

Stanimir Stamenkov

Sun, 18 Sep 2011 09:50:03 -0400, /Eric Sosman/:
I do not know whether buffer-sharing was dropped before, after,
or with the introduction of StringBuilder.

I don't know when the implementation has changed, also, but here's
my guess on why it might have changed to make a copy. Previously
I've often used:

StringBuffer buf;
...
String str = buf.substring(0, buf.length());

to have the constructed String internal char[] always occupying
exactly the size needed to hold the text. Previously, with
StringBuffer.toString() the String could hold as much as twice
bigger char[] than needed. If one constructs long lived String
objects that way, the memory usage could grow unnecessary high.
 
J

Jan Burse

Eric said:
I do not know whether buffer-sharing was dropped before, after,
or with the introduction of StringBuilder.

The implementation advice comment was removed in 1.5 javadoc.
It was still present in 1.4.1 javadoc:


1.4.1 javadoc:

Converts to a string representing the data in this string buffer. A new
String object is allocated and initialized to contain the character
sequence currently represented by this string buffer. This String is
then returned. Subsequent changes to the string buffer do not affect the
contents of the String.

Implementation advice: This method can be coded so as to create a new
String object without allocating new memory to hold a copy of the
character sequence. Instead, the string can share the memory used by the
string buffer. Any subsequent operation that alters the content or
capacity of the string buffer must then make a copy of the internal
buffer at that time. This strategy is effective for reducing the amount
of memory allocated by a string concatenation operation when it is
implemented using a string buffer.

http://download.oracle.com/javase/1.4.2/docs/api/java/lang/StringBuffer.html#toString()





1.5 javadoc:

Returns a string representing the data in this sequence. A new String
object is allocated and initialized to contain the character sequence
currently represented by this object. This String is then returned.
Subsequent changes to this sequence do not affect the contents of the
String.

http://download.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuffer.html#toString()



Bye
 
J

Jan Burse

Jan said:
The implementation advice comment was removed in 1.5 javadoc.
It was still present in 1.4.1 javadoc:

But I don't see the AbstractStringBuilder in the Oracle javadoc,
maybe it is filtered out since it is package local(*). Or the class
is specific to OpenJDK, not sure. Slowly getting confused, not
feeling comfortable starting a dozen of different machines to
check the JDK installation... Dammned, isn't there a website
where we see such things side by side?

But StringBuilder has a @since 1.5 tag, so this is the earliest
moment for this class to look for a javadoc.

Bye

P.S.: It really seems that it is filtered out, David Flanagan
was confronted with it:

This is the first instance that I am aware of of
a public class extending a non-public one, and it
raises questions about documenting the public one.
The javadoc team dealt with it by simply pretending
that the non-public intermediary class does not
exist. Now I have to figure out how to document
this for Java in a Nutshell.

http://www.davidflanagan.com/2004/10/abstractstringbuilder.html
 
J

Jan Burse

Jan said:
P.S.: It really seems that it is filtered out, David Flanagan
was confronted with it:

BTW he is moaning that AbstractStringBuilder is not public:

"It seems to me that this was a real missed opportunity. If
AbstractStringBuilder had been public we could write methods
that would work with either a StringBuffer or a
StringBuilder argument."

Well we could still go to some extend with the interfaces
Appendable and Charsequence.

An example with a non package local abstract superclass would
be Vector and ArrayList, they are also synchronized and non-
synchronized implementations of a now public class AbstractList.

Bye
 
R

Roedy Green

I wasn't.
What I was saying was that (maybe my english is not good enough our you
deliberately want to misunderstand me, just to "win a discussion")

Lew really wanted to be a prosecution lawyer. It is good practice
talking to him. He forces you to use precisely correct and unambiguous
language. However I admit he takes an unusually savage glee in
humiliating ESL students. Maybe his wife beats him.

--
Roedy Green Canadian Mind Products
http://mindprod.com
It is a lot easier to combine things later that
have been too finely categorised than to split
things later whose are categories are too coarse.
 
J

Jeff Higgins

Read it and weep.
Lew really wanted to be a prosecution lawyer. It is good practice
talking to him. He forces you to use precisely correct and unambiguous
language. However I admit he takes an unusually savage glee in
humiliating ESL students. Maybe his wife beats him.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top