Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #25328 > unrolled thread

StringBuilder.append and CharSequence

Started byAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
First post2013-09-25 14:19 +0000
Last post2013-09-27 15:41 +0300
Articles 20 — 5 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  StringBuilder.append and CharSequence Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-09-25 14:19 +0000
    Re: StringBuilder.append and CharSequence markspace <markspace@nospam.nospam> - 2013-09-25 13:02 -0700
      Re: StringBuilder.append and CharSequence markspace <markspace@nospam.nospam> - 2013-09-25 18:34 -0700
        Re: StringBuilder.append and CharSequence Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-09-26 17:37 +0000
          Re: StringBuilder.append and CharSequence Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2013-09-26 23:11 +0200
            Re: StringBuilder.append and CharSequence Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-09-27 13:30 +0000
              Re: StringBuilder.append and CharSequence Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2013-09-27 19:31 +0200
                Re: StringBuilder.append and CharSequence markspace <markspace@nospam.nospam> - 2013-09-27 13:45 -0700
                  Re: StringBuilder.append and CharSequence Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-09-27 23:16 +0000
                    Re: StringBuilder.append and CharSequence Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2013-09-29 04:58 +0200
                      Re: StringBuilder.append and CharSequence Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-09-30 20:02 +0000
    Re: StringBuilder.append and CharSequence Arne Vajhøj <arne@vajhoej.dk> - 2013-09-25 20:57 -0400
      Re: StringBuilder.append and CharSequence Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-09-26 18:01 +0000
        Re: StringBuilder.append and CharSequence Arne Vajhøj <arne@vajhoej.dk> - 2013-09-26 15:47 -0400
          Re: StringBuilder.append and CharSequence Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-09-26 20:48 +0000
            Re: StringBuilder.append and CharSequence Arne Vajhøj <arne@vajhoej.dk> - 2013-09-26 16:58 -0400
              Re: StringBuilder.append and CharSequence Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-09-27 12:52 +0000
                Re: StringBuilder.append and CharSequence Arne Vajhøj <arne@vajhoej.dk> - 2013-10-04 20:59 -0400
                  Re: StringBuilder.append and CharSequence Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-10-05 12:51 +0000
    Re: StringBuilder.append and CharSequence Sven Köhler <remove-sven.koehler@gmail.com> - 2013-09-27 15:41 +0300

#25328 — StringBuilder.append and CharSequence

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-09-25 14:19 +0000
SubjectStringBuilder.append and CharSequence
Message-ID<slrnl45s71.mol.avl@gamma.logic.tuwien.ac.at>
Is it safe to use "stringBuilder.append(this);" in a CharSequence
implementation's .toString(), or could this lead to a recursive
loop, if some version of a Java class library implements the
append() for CharSequence by using it's toString() ?

I read the javadoc for StringBuilder/Appendable.append(CharSequence)
but it isn't clear to me.

[toc] | [next] | [standalone]


#25337

Frommarkspace <markspace@nospam.nospam>
Date2013-09-25 13:02 -0700
Message-ID<l1vfg6$mi$1@dont-email.me>
In reply to#25328
On 9/25/2013 7:19 AM, Andreas Leitgeb wrote:
> Is it safe to use "stringBuilder.append(this);"

It wasn't clear to me either from reading the Java docs that the above 
was safe, so I'd avoid it.

> in a CharSequence
> implementation's .toString(), or could this lead to a recursive
> loop, if some version of a Java class library implements the
> append() for CharSequence by using it's toString() ?

That paragraph wasn't clear to me at all.  I was going to suggest 
toString() as the safe approach.

   stringBuilder.append( this.toString() );

This seems bomb proof to me, as the string is constructed before the 
method call.  Did I miss something?

[toc] | [prev] | [next] | [standalone]


#25345

Frommarkspace <markspace@nospam.nospam>
Date2013-09-25 18:34 -0700
Message-ID<l202uq$ae1$1@dont-email.me>
In reply to#25337
On 9/25/2013 1:02 PM, markspace wrote:
> On 9/25/2013 7:19 AM, Andreas Leitgeb wrote:
>> Is it safe to use "stringBuilder.append(this);"
>
> It wasn't clear to me either from reading the Java docs that the above
> was safe, so I'd avoid it.
>
>> in a CharSequence
>> implementation's .toString(), or could this lead to a recursive
>> loop, if some version of a Java class library implements the
>> append() for CharSequence by using it's toString() ?
>
> That paragraph wasn't clear to me at all.  I was going to suggest
> toString() as the safe approach.
>
>    stringBuilder.append( this.toString() );
>
> This seems bomb proof to me, as the string is constructed before the
> method call.  Did I miss something?

Actually, I mis-read your problem statement, I think.  Having 
implemented a couple of CharSequence classes, the only rational approach 
would be to copy the chars out of a CharSequence one at a time with a 
loop and charAt().  toString() must create an immutable String and so 
must create a new buffer, so that's an extra buffer copy, which seems 
undesirable no matter who's implementing the append() method.  However I 
wouldn't call toString(), as that would obviously create a stack overflow.

I would think that you must have some much better method of copying 
characters though, as you should have access to your own private fields.

   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
     sb.append( myCharArray, start, length );
     return sb.toString();
   }

This obviously could be done with a single "new String(..." but I'm just 
trying to hammer the idea home that there's internal fields to use.


[toc] | [prev] | [next] | [standalone]


#25360

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-09-26 17:37 +0000
Message-ID<slrnl48s79.mol.avl@gamma.logic.tuwien.ac.at>
In reply to#25345
markspace <markspace@nospam.nospam> wrote:
> On 9/25/2013 1:02 PM, markspace wrote:
>> On 9/25/2013 7:19 AM, Andreas Leitgeb wrote:
>>> Is it safe to use "stringBuilder.append(this);" in a CharSequence
>>> implementation's .toString(), or could this lead to a recursive
>>> loop, if some version of a Java class library implements the
>>> append() for CharSequence by using it's toString() ?
>> [...]
> Actually, I mis-read your problem statement, I think.  Having 
> implemented a couple of CharSequence classes, the only rational approach 
> would be to copy the chars out of a CharSequence one at a time with a 
> loop and charAt().  toString() must create an immutable String and so 
> must create a new buffer, so that's an extra buffer copy, which seems 
> undesirable no matter who's implementing the append() method.

That's my point. My outset is, that eventually I need to append a number
of copies of some particular char to a StringBuilder, and my approach is:

   static class ChSeq implements CharSequence {
      int m_len; char m_ch;
      public ChSeq(int len, char ch) { m_len = len; m_ch = ch; }
      public char charAt(int pos) { return m_ch; }// OutOfBounds? meh!
      public int length() { return m_len; }
      public String toString() { // just 'cause it's required...
        return new StringBuilder(this).toString(); }
      public CharSequence subSequence(int fr,int to) {
        return ChSeq(to-fr,m_ch); }
   } // not yet tested!
   // then later:
   sb.append( new ChSeq(n,ch) );

This would look like a reasonable OO approach to the problem, but
if StringBuilder.append actually used my .toString(), then it would
of course crash&burn.

If instead I had to implement the toString() by doing the loop myself
and hammer the char n times to the temporary StringBuilder, then I'd
instead just write a static method that would take sb,n,ch and feed n
copies of ch to sb.

[toc] | [prev] | [next] | [standalone]


#25365

FromDaniele Futtorovic <da.futt.news@laposte-dot-net.invalid>
Date2013-09-26 23:11 +0200
Message-ID<l227v3$f6i$1@dont-email.me>
In reply to#25360
On 2013-09-26 19:37, Andreas Leitgeb allegedly wrote:
> markspace <markspace@nospam.nospam> wrote:
>> On 9/25/2013 1:02 PM, markspace wrote:
>>> On 9/25/2013 7:19 AM, Andreas Leitgeb wrote:
>>>> Is it safe to use "stringBuilder.append(this);" in a CharSequence
>>>> implementation's .toString(), or could this lead to a recursive
>>>> loop, if some version of a Java class library implements the
>>>> append() for CharSequence by using it's toString() ?
>>> [...]
>> Actually, I mis-read your problem statement, I think.  Having 
>> implemented a couple of CharSequence classes, the only rational approach 
>> would be to copy the chars out of a CharSequence one at a time with a 
>> loop and charAt().  toString() must create an immutable String and so 
>> must create a new buffer, so that's an extra buffer copy, which seems 
>> undesirable no matter who's implementing the append() method.
> 
> That's my point. My outset is, that eventually I need to append a number
> of copies of some particular char to a StringBuilder, and my approach is:
> 
>    static class ChSeq implements CharSequence {
>       int m_len; char m_ch;
>       public ChSeq(int len, char ch) { m_len = len; m_ch = ch; }
>       public char charAt(int pos) { return m_ch; }// OutOfBounds? meh!
>       public int length() { return m_len; }
>       public String toString() { // just 'cause it's required...
>         return new StringBuilder(this).toString(); }
>       public CharSequence subSequence(int fr,int to) {
>         return ChSeq(to-fr,m_ch); }
>    } // not yet tested!
>    // then later:
>    sb.append( new ChSeq(n,ch) );
> 
> This would look like a reasonable OO approach to the problem, but
> if StringBuilder.append actually used my .toString(), then it would
> of course crash&burn.
> 
> If instead I had to implement the toString() by doing the loop myself
> and hammer the char n times to the temporary StringBuilder, then I'd
> instead just write a static method that would take sb,n,ch and feed n
> copies of ch to sb.
> 

I'd make the toString() as follows to be on the safe side:
  char[] cs = new char[ m_len ];
  Arrays.fill( cs, m_ch );
  return new String(cs);

If that hits performance, then you have got a conflict between your goal
of being OO and that of performance, and you'll have to scrap one.

-- 
DF.

[toc] | [prev] | [next] | [standalone]


#25370

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-09-27 13:30 +0000
Message-ID<slrnl4b22r.mol.avl@gamma.logic.tuwien.ac.at>
In reply to#25365
Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> wrote:
> I'd make the toString() as follows to be on the safe side:
>   char[] cs = new char[ m_len ];
>   Arrays.fill( cs, m_ch );
>   return new String(cs);

If this is the ONLY safe side, then there wouldn't be a point
in implementing a CharSequence in the first place for my task.

The apparent point for CharSequence was, that it looked like a
vehicle to pass a number and a char into StringBuilder.append().

> If that hits performance, then you have got a conflict between your goal
> of being OO and that of performance, and you'll have to scrap one.

If the OO path for a task turns out goofy, then I pick the other one.

PS: there's probably also a third path: copying StringBuilder.java from
  src.zip and adding an .append(int n, char ch) overload. ;)

[toc] | [prev] | [next] | [standalone]


#25375

FromDaniele Futtorovic <da.futt.news@laposte-dot-net.invalid>
Date2013-09-27 19:31 +0200
Message-ID<l24fdo$ius$1@dont-email.me>
In reply to#25370
On 2013-09-27 15:30, Andreas Leitgeb allegedly wrote:
> Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> wrote:
>> I'd make the toString() as follows to be on the safe side:
>>   char[] cs = new char[ m_len ];
>>   Arrays.fill( cs, m_ch );
>>   return new String(cs);
> 
> If this is the ONLY safe side, then there wouldn't be a point
> in implementing a CharSequence in the first place for my task.

Why not? The Standard API's StringBuilder#append(CharSequence), AFAICS,
does not call toString() -- granted, the JavaDoc stipulates nothing to
that effect.

> The apparent point for CharSequence was, that it looked like a
> vehicle to pass a number and a char into StringBuilder.append().

-- 
DF.

[toc] | [prev] | [next] | [standalone]


#25376

Frommarkspace <markspace@nospam.nospam>
Date2013-09-27 13:45 -0700
Message-ID<l24qp9$mco$1@dont-email.me>
In reply to#25375
On 9/27/2013 10:31 AM, Daniele Futtorovic wrote:
> On 2013-09-27 15:30, Andreas Leitgeb allegedly wrote:
>> Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> wrote:
>>> I'd make the toString() as follows to be on the safe side:
>>>    char[] cs = new char[ m_len ];
>>>    Arrays.fill( cs, m_ch );
>>>    return new String(cs);
>>
>> If this is the ONLY safe side, then there wouldn't be a point
>> in implementing a CharSequence in the first place for my task.
>
> Why not? The Standard API's StringBuilder#append(CharSequence), AFAICS,
> does not call toString() -- granted, the JavaDoc stipulates nothing to
> that effect.

I read Andreas's comment as "there's not point introducing a new type if 
a repeated string is just always turned into a regular String anyway."

If your new type can be easily replaced with a static method:

   public static String repeated( char c, int count ) {
     final char[] ca = new char[ count ];
     Arrays.fill( ca, c );
     return new String( ca );
   }

Then there's really no need to introduce a new type.  However I'm not 
100% confident that I'm following his line of thought.


[toc] | [prev] | [next] | [standalone]


#25377

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-09-27 23:16 +0000
Message-ID<slrnl4c4di.mol.avl@gamma.logic.tuwien.ac.at>
In reply to#25376
markspace <markspace@nospam.nospam> wrote:
> On 9/27/2013 10:31 AM, Daniele Futtorovic wrote:
>> On 2013-09-27 15:30, Andreas Leitgeb allegedly wrote:
>>> Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> wrote:
>>>> I'd make the toString() as follows to be on the safe side:
>>>>    char[] cs = new char[ m_len ];
>>>>    Arrays.fill( cs, m_ch );
>>>>    return new String(cs);
>>> If this is the ONLY safe side, then there wouldn't be a point
>>> in implementing a CharSequence in the first place for my task.
>> Why not? The Standard API's StringBuilder#append(CharSequence), AFAICS,
>> does not call toString() -- granted, the JavaDoc stipulates nothing to
>> that effect.
>
> I read Andreas's comment as "there's not point introducing a new type if 
> a repeated string is just always turned into a regular String anyway."

Yes, that's about it.

The "new type" is the ChSeq from a few posts upthread.
The "repeated string" is a possibly long repetition of
just a single char, compactly represented by ChSeq...

[toc] | [prev] | [next] | [standalone]


#25385

FromDaniele Futtorovic <da.futt.news@laposte-dot-net.invalid>
Date2013-09-29 04:58 +0200
Message-ID<l2850h$9nf$1@dont-email.me>
In reply to#25377
On 2013-09-28 01:16, Andreas Leitgeb allegedly wrote:
> markspace <markspace@nospam.nospam> wrote:
>> On 9/27/2013 10:31 AM, Daniele Futtorovic wrote:
>>> On 2013-09-27 15:30, Andreas Leitgeb allegedly wrote:
>>>> Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> wrote:
>>>>> I'd make the toString() as follows to be on the safe side:
>>>>>    char[] cs = new char[ m_len ];
>>>>>    Arrays.fill( cs, m_ch );
>>>>>    return new String(cs);
>>>> If this is the ONLY safe side, then there wouldn't be a point
>>>> in implementing a CharSequence in the first place for my task.
>>> Why not? The Standard API's StringBuilder#append(CharSequence), AFAICS,
>>> does not call toString() -- granted, the JavaDoc stipulates nothing to
>>> that effect.
>>
>> I read Andreas's comment as "there's not point introducing a new type if 
>> a repeated string is just always turned into a regular String anyway."
> 
> Yes, that's about it.
> 
> The "new type" is the ChSeq from a few posts upthread.
> The "repeated string" is a possibly long repetition of
> just a single char, compactly represented by ChSeq...
> 

Yes, but using the ChSeq (as it was introduced) to append it to a
StringBuilder WILL NOT, as the JSE currently stands, result in the
invocation of toString(). So you are safe to go.

Then, as far as the implementation of toString() is concerned (which
only matters if other API use your ChSeq's), I would say it ought to be
implemented as above, for safety reasons and because, after all, since
every String uses a char[] buffer, it stands to reason that you cannot
produce a String, which toString() is supposed to do, without allocating
such a buffer (as an optimisation, you could create it but once on demand).

Incidentally, while I know no place in the documentation that expresses
it, it is likely the case that all API designed to handle CharSequence's
will operate on a by-char-basis (as opposed to calling toString() ) if
they can afford it at all -- seeing how this is what the CharSequence
interface is all about.

-- 
DF.

[toc] | [prev] | [next] | [standalone]


#25397

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-09-30 20:02 +0000
Message-ID<slrnl4jm6s.mol.avl@gamma.logic.tuwien.ac.at>
In reply to#25385
Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> wrote:
> On 2013-09-28 01:16, Andreas Leitgeb allegedly wrote:
>> markspace <markspace@nospam.nospam> wrote:
>>> On 9/27/2013 10:31 AM, Daniele Futtorovic wrote:
>>>> On 2013-09-27 15:30, Andreas Leitgeb allegedly wrote:
>>>>> Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> wrote:
>>>>>> I'd make the toString() as follows to be on the safe side:
>>>>>>    char[] cs = new char[ m_len ];
>>>>>>    Arrays.fill( cs, m_ch );
>>>>>>    return new String(cs);
>>>>> If this is the ONLY safe side, then there wouldn't be a point
>>>>> in implementing a CharSequence in the first place for my task.
>>>> Why not? The Standard API's StringBuilder#append(CharSequence), AFAICS,
>>>> does not call toString() -- granted, the JavaDoc stipulates nothing to
>>>> that effect.
>>> I read Andreas's comment as "there's not point introducing a new type if 
>>> a repeated string is just always turned into a regular String anyway."
>> Yes, that's about it.
>> The "new type" is the ChSeq from a few posts upthread.
>> The "repeated string" is a possibly long repetition of
>> just a single char, compactly represented by ChSeq...
>
> Yes, but using the ChSeq (as it was introduced) to append it to a
> StringBuilder WILL NOT, as the JSE currently stands, result in the
> invocation of toString(). So you are safe to go.

As much as I'd like this answer... "safe" is a strong word, and
seeing a particular Java implementation *not* call toString() is
sufficient for my task for now, but not not sufficient for "safe".

> Then, as far as the implementation of toString() is concerned (which
> only matters if other API use your ChSeq's)

My application definitely doesn't call toString() on the ChSeq-instances,
but a debugger might do it.
I thought of implementing toString() to create a String like
  "42000000 times '*'"
making it even more suitable for debugger inspection than the canonical
expansion, but unfortunately that would definitely break the specified
contract of CharSequence.toString().

I think, this topic has been thoroughly discussed now.
Thanks to all who participated.

[toc] | [prev] | [next] | [standalone]


#25340

FromArne Vajhøj <arne@vajhoej.dk>
Date2013-09-25 20:57 -0400
Message-ID<52438692$0$292$14726298@news.sunsite.dk>
In reply to#25328
On 9/25/2013 10:19 AM, Andreas Leitgeb wrote:
> Is it safe to use "stringBuilder.append(this);" in a CharSequence
> implementation's .toString(), or could this lead to a recursive
> loop, if some version of a Java class library implements the
> append() for CharSequence by using it's toString() ?
>
> I read the javadoc for StringBuilder/Appendable.append(CharSequence)
> but it isn't clear to me.


Good question.

Java docs for StringBuilder says:

<quote>
The principal operations on a StringBuilder are the append and insert 
methods, which are overloaded so as to accept data of any type. Each 
effectively converts a given datum to a string and then appends or 
inserts the characters of that string to the string builder.
</quote>

Based on the use of "string" and "and then" I interpret this as:

<interpretation>
Append has two distinct sequential phases:
1) convert the argument to an instance of java.util.String
2) append that to the StringBuilder
</interpretation>

And that would mean that:

sb.append(sb);

is a safe and well defined operation.

But given that developers occasionally makes mistakes in
both java docs and implementation, then I would never rely
on that.

Especially since the simple rewrite to:

sb.append(sb.toString());

will ensure the desired semantics.

Arne




[toc] | [prev] | [next] | [standalone]


#25361

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-09-26 18:01 +0000
Message-ID<slrnl48tkb.mol.avl@gamma.logic.tuwien.ac.at>
In reply to#25340
Arne Vajhøj <arne@vajhoej.dk> wrote:
> On 9/25/2013 10:19 AM, Andreas Leitgeb wrote:
>> Is it safe to use "stringBuilder.append(this);" in a CharSequence
>> implementation's .toString(), or could this lead to a recursive
>> loop, if some version of a Java class library implements the
>> append() for CharSequence by using it's toString() ?
>> I read the javadoc for StringBuilder/Appendable.append(CharSequence)
>> but it isn't clear to me.
>
> Java docs for StringBuilder says:
> <quote>
> The principal operations on a StringBuilder are the append and insert 
> methods, which are overloaded so as to accept data of any type. Each 
> effectively converts a given datum to a string and then appends or 
> inserts the characters of that string to the string builder.
> </quote>
>
> Based on the use of "string" and "and then" I interpret this as:
> <interpretation>
> Append has two distinct sequential phases:
> 1) convert the argument to an instance of java.util.String
> 2) append that to the StringBuilder
> </interpretation>

If .append() used .toString(), then there wouldn't be a point for offering
a CharSequence overload. It could then just offer one overload for Object
(apart from those for primitive types), and be set.

So, while the documentation's verbiage is unclear, other facts appear to
hint towards a reasonable behaviour that avoids any unnecessary temporary
String instance.

> And that would mean that:
> sb.append(sb);
> is a safe and well defined operation.

That would work even without the detour to String, as long as StringBuilder
captures the initial *length()* of the passed CharSequence (itself), and then
only appended that number of chars.

StringBuilder's insert() is a much more delicate test case, as the Javadoc
for .insert() doesn't seem to take into account, that the given CharSequence
might "magically" change during the operation.

[toc] | [prev] | [next] | [standalone]


#25362

FromArne Vajhøj <arne@vajhoej.dk>
Date2013-09-26 15:47 -0400
Message-ID<52448f70$0$303$14726298@news.sunsite.dk>
In reply to#25361
On 9/26/2013 2:01 PM, Andreas Leitgeb wrote:
> Arne Vajhøj <arne@vajhoej.dk> wrote:
>> On 9/25/2013 10:19 AM, Andreas Leitgeb wrote:
>>> Is it safe to use "stringBuilder.append(this);" in a CharSequence
>>> implementation's .toString(), or could this lead to a recursive
>>> loop, if some version of a Java class library implements the
>>> append() for CharSequence by using it's toString() ?
>>> I read the javadoc for StringBuilder/Appendable.append(CharSequence)
>>> but it isn't clear to me.
>>
>> Java docs for StringBuilder says:
>> <quote>
>> The principal operations on a StringBuilder are the append and insert
>> methods, which are overloaded so as to accept data of any type. Each
>> effectively converts a given datum to a string and then appends or
>> inserts the characters of that string to the string builder.
>> </quote>
>>
>> Based on the use of "string" and "and then" I interpret this as:
>> <interpretation>
>> Append has two distinct sequential phases:
>> 1) convert the argument to an instance of java.util.String
>> 2) append that to the StringBuilder
>> </interpretation>
>
> If .append() used .toString(), then there wouldn't be a point for offering
> a CharSequence overload. It could then just offer one overload for Object
> (apart from those for primitive types), and be set.

Yes. But "convert the argument to an instance of java.util.String" is
not the same as calling .toString(), so I don't see that as an argument.

> So, while the documentation's verbiage is unclear,

"string" and "and then" are no that unclear to me.

>                                                    other facts appear to
> hint towards a reasonable behaviour that avoids any unnecessary temporary
> String instance.

Like?

>> And that would mean that:
>> sb.append(sb);
>> is a safe and well defined operation.
>
> That would work even without the detour to String, as long as StringBuilder
> captures the initial *length()* of the passed CharSequence (itself), and then
> only appended that number of chars.

Yes. But then you are making assumptions about the implementation.

Saving creating an extra String object is not worth it.

If you need really high performance code, then write something
special for it.

Arne

[toc] | [prev] | [next] | [standalone]


#25363

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-09-26 20:48 +0000
Message-ID<slrnl497c6.mol.avl@gamma.logic.tuwien.ac.at>
In reply to#25362
Arne Vajhøj <arne@vajhoej.dk> wrote:
> On 9/26/2013 2:01 PM, Andreas Leitgeb wrote:
>> Arne Vajhøj <arne@vajhoej.dk> wrote:
>>> On 9/25/2013 10:19 AM, Andreas Leitgeb wrote:
>>>> Is it safe to use "stringBuilder.append(this);" in a CharSequence
>>>> implementation's .toString(), or could this lead to a recursive
>>>> loop, if some version of a Java class library implements the
>>>> append() for CharSequence by using it's toString() ?
>>> <quote>
>>> The principal operations on a StringBuilder are the append and insert
>>> methods, which are overloaded so as to accept data of any type. Each
>>> effectively converts a given datum to a string and then appends or
>>> inserts the characters of that string to the string builder.
>>> </quote>
>>>
>>> Based on the use of "string" and "and then" I interpret this as:
>>> <interpretation>
>>> Append has two distinct sequential phases:
>>> 1) convert the argument to an instance of java.util.String

I only noticed this now:  "java.util.String" - is that a typo for
java.lang.String, or is there really a (non-public) java.util.String?

>>> 2) append that to the StringBuilder
>>> </interpretation>
>>
>> If .append() used .toString(), then there wouldn't be a point for offering
>> a CharSequence overload. It could then just offer one overload for Object
>> (apart from those for primitive types), and be set.
> Yes. But "convert the argument to an instance of java.util.String" is
> not the same as calling .toString()

append() might create a snapshot-copy of the CharSequence, and it doesn't
matter if that is in some extra non-public class, a simple char[] or the
well-known java.lang.String.  What *does* matter (at least to me, who
started this thread) is, whether it uses Object.toString() or the specific
CharSequence methods to obtain that snapshot.

Although the docs aren't explicit on this, they now appear to imply it
well enough for me to firmly believe the latter.

Mostly, because the docs for append(Object) *are* explicit about using
String.valueOf(obj) (and thus indirectly toString(), unless null)

[toc] | [prev] | [next] | [standalone]


#25364

FromArne Vajhøj <arne@vajhoej.dk>
Date2013-09-26 16:58 -0400
Message-ID<5244a015$0$302$14726298@news.sunsite.dk>
In reply to#25363
On 9/26/2013 4:48 PM, Andreas Leitgeb wrote:
> Arne Vajhøj <arne@vajhoej.dk> wrote:
>> On 9/26/2013 2:01 PM, Andreas Leitgeb wrote:
>>> Arne Vajhøj <arne@vajhoej.dk> wrote:
>>>> On 9/25/2013 10:19 AM, Andreas Leitgeb wrote:
>>>>> Is it safe to use "stringBuilder.append(this);" in a CharSequence
>>>>> implementation's .toString(), or could this lead to a recursive
>>>>> loop, if some version of a Java class library implements the
>>>>> append() for CharSequence by using it's toString() ?
>>>> <quote>
>>>> The principal operations on a StringBuilder are the append and insert
>>>> methods, which are overloaded so as to accept data of any type. Each
>>>> effectively converts a given datum to a string and then appends or
>>>> inserts the characters of that string to the string builder.
>>>> </quote>
>>>>
>>>> Based on the use of "string" and "and then" I interpret this as:
>>>> <interpretation>
>>>> Append has two distinct sequential phases:
>>>> 1) convert the argument to an instance of java.util.String
>
> I only noticed this now:  "java.util.String" - is that a typo for
> java.lang.String, or is there really a (non-public) java.util.String?

Typo.

java.lang.String ofcourse.

>>>> 2) append that to the StringBuilder
>>>> </interpretation>
>>>
>>> If .append() used .toString(), then there wouldn't be a point for offering
>>> a CharSequence overload. It could then just offer one overload for Object
>>> (apart from those for primitive types), and be set.
>> Yes. But "convert the argument to an instance of java.util.String" is
>> not the same as calling .toString()
>
> append() might create a snapshot-copy of the CharSequence, and it doesn't
> matter if that is in some extra non-public class, a simple char[] or the
> well-known java.lang.String.  What *does* matter (at least to me, who
> started this thread) is, whether it uses Object.toString() or the specific
> CharSequence methods to obtain that snapshot.
>
> Although the docs aren't explicit on this, they now appear to imply it
> well enough for me to firmly believe the latter.

Either they do that or they have to ensure that the functionality is the
same as that.

But I would still be a bit worried if the code has to be supported by
non mainstream Java implementations.

And why not call .toString explicit? Is the code that
performance critical?

Arne

[toc] | [prev] | [next] | [standalone]


#25369

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-09-27 12:52 +0000
Message-ID<slrnl4avs3.mol.avl@gamma.logic.tuwien.ac.at>
In reply to#25364
Arne Vajhøj <arne@vajhoej.dk> wrote:
> And why not call .toString explicit? Is the code that
> performance critical?

I'm not optimizing for performance, but I'm always - from the
first line of code that I write - optimizing for a property
that I'd call "don't do goofy stuff."

To me, creating a CharSequence(implementation) instance that wraps
the length and the char, is NOT goofy.

Otoh, creating a temporary object (be it String or char[]) that
holds the given number of copies of a single char IS goofy in my
vocabulary.

If a CharSequence is a vehicle to transport the char and the number
into StringBuilder's reach, then this is some big boilerplate substitute
for the sorely missing .append(int num, char ch) method, but not goofy.

If this CharSequence was then merely used to create a big dull
temp object via toString(), then it goes right back to "goofy".

[toc] | [prev] | [next] | [standalone]


#26231

FromArne Vajhøj <arne@vajhoej.dk>
Date2013-10-04 20:59 -0400
Message-ID<524f6470$0$302$14726298@news.sunsite.dk>
In reply to#25369
On 9/27/2013 8:52 AM, Andreas Leitgeb wrote:
> Arne Vajhøj <arne@vajhoej.dk> wrote:
>> And why not call .toString explicit? Is the code that
>> performance critical?
>
> I'm not optimizing for performance, but I'm always - from the
> first line of code that I write - optimizing for a property
> that I'd call "don't do goofy stuff."
>
> To me, creating a CharSequence(implementation) instance that wraps
> the length and the char, is NOT goofy.
>
> Otoh, creating a temporary object (be it String or char[]) that
> holds the given number of copies of a single char IS goofy in my
> vocabulary.
>
> If a CharSequence is a vehicle to transport the char and the number
> into StringBuilder's reach, then this is some big boilerplate substitute
> for the sorely missing .append(int num, char ch) method, but not goofy.
>
> If this CharSequence was then merely used to create a big dull
> temp object via toString(), then it goes right back to "goofy".

As far as I cann then the .toString solution is readable and
maintainable.

I would not worry about temporary object being created
unless I observe an actual problem.

I don't think it is goofy. It may not be elegant. But elegant
is not a business goal.

Arne

[toc] | [prev] | [next] | [standalone]


#26234

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-10-05 12:51 +0000
Message-ID<slrnl502pq.mol.avl@gamma.logic.tuwien.ac.at>
In reply to#26231
Arne Vajhøj <arne@vajhoej.dk> wrote:
> On 9/27/2013 8:52 AM, Andreas Leitgeb wrote:
>> If a CharSequence is a vehicle to transport the char and the number
>> into StringBuilder's reach, then this is some big boilerplate substitute
>> for the sorely missing .append(int num, char ch) method, but not goofy.
>>
>> If this CharSequence was then merely used to create a big dull
>> temp object via toString(), then it goes right back to "goofy".
> I would not worry about temporary object being created
> unless I observe an actual problem.

I had considered this thread done already, but since there is further
interest...

There's really two aspects to my original problem.
 1) will any temporary object be created when append()ing a CharSequence
      to a StringBuilder?
 2) might StringBuilder eventually call a CharSequence's toString() from
      within it's .append()?

A positive answer for 2) would also imply "yes" for 1), of course.
Given the *current* implementation of Oracle's implementation,
  the answer to both questions is (fortunately) negative.
Even the consequences of a "1) yes 2) no" reply would not really be
  as "earth-shattering" as I might have implied so far in this thread.

Now, for question 2)

There'll be essentially two kinds of CharSequence implementations:
 a) some kind of "mutable String-alike", like e.g. StringBuilder.
      these likely save their data in some char[] already, and 
      creating a String of that is trivial.
 b) those that "calculate" each char in charAt().
      My ChSeq falls into that category, and maybe a couple other
      special purpose ones.

For those of kind b), being allowed to slam "this" to a StringBuilder
and then have the StringBuilder create a String object, would sound like
a nice example of code-reuse, compared to having to write the loop and
append-call for each char.

I don't really have any idea, how many CharSequence implementations
of kind b) really exist in the world, and it is not unlikely, that
they are far too few to justify any thought at all, but nevertheless,
I wish that StringBuilder.append() were SPECIFIED to use CharSequence-
API (i.e. essentially length() and charAt(), as is already implemented)
to SAFELY allow for trivial .toString() implementations in those classes.

[toc] | [prev] | [next] | [standalone]


#25368

FromSven Köhler <remove-sven.koehler@gmail.com>
Date2013-09-27 15:41 +0300
Message-ID<balcnbFtkrhU1@mid.dfncis.de>
In reply to#25328
Am 25.09.2013 17:19, schrieb Andreas Leitgeb:
> Is it safe to use "stringBuilder.append(this);" in a CharSequence
> implementation's .toString(), or could this lead to a recursive
> loop, if some version of a Java class library implements the
> append() for CharSequence by using it's toString() ?
> 
> I read the javadoc for StringBuilder/Appendable.append(CharSequence)
> but it isn't clear to me.

To me, this isn't clear either. However, I wonder:
What keeps you from writing safe code? I would suspect, that your
CharSequence might store some kind of char array. So why not call the
corresponding append method? Or even if it does not store a char array,
then why not write the for loop to append char by char? It's just 2
lines and it's probably not even slower.


Regards,
  Sven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web