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 / July 2006

Tip: Looking for answers? Try searching our database.

Converting char(s) into String

Thread view: 
ponga - 08 Jun 2006 19:08 GMT
I spent hours trying to figure this out, so for others benifit, here it
is:

I had a problem trying to concatenate a few characters into a String.
This was what I was trying to do, with no success:
String s1 = "Some text";
String str =  s1.charAt(0) + s1.charAt(5);
Oddly enough, Eclipse threw a "Type mismatch: cannot convert from int
to String"
int?? Anyway, I battled this for a few hours and here is what works:
String str = "" + s1.charAt(0) + s1.charAt(5);

WTF?
Anyway, there you have it.
-Mike
John O'Conner - 08 Jun 2006 19:14 GMT
> I spent hours trying to figure this out, so for others benifit, here it
> is:
[quoted text clipped - 7 lines]
> int?? Anyway, I battled this for a few hours and here is what works:
> String str = "" + s1.charAt(0) + s1.charAt(5);

s1.charAt(0) returns a char, s1.charAt(5) returns a char. Now you try to
add them, and the chars turn into int types for that process. The result
is an int. Then you try to assign into str, which is String type. Note:
the '+' operator is only overloaded for String concatenation, not char
concatenation to produce strings.

Voila! a type mismatch.

Maybe a less confusing way to do this is this:

StringBuffer strBuf = new StringBuffer();
strBuff.append(s1.charAt(0));
strBuff.append(s1.charAt(5));

--
John O'Conner
Thomas Hawtin - 08 Jun 2006 19:40 GMT
>> String str = "" + s1.charAt(0) + s1.charAt(5);

> Maybe a less confusing way to do this is this:
>
> StringBuffer strBuf = new StringBuffer();
> strBuff.append(s1.charAt(0));
> strBuff.append(s1.charAt(5));
  String str = strBuff.toString();

One thing to be aware of is that passing a char to the constructor does
not do what you may expect.

String str =
    new StringBuilder(s1.charAt(0)).append(s2.charAt(5)).toString();

You don't need to go through StringBuffer (or better StringBuilder) for
something this simple.

String str = String.valueOf(new char[] { s1.charAt(0), s1.charAt(5) });

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

amitdev@gmail.com - 09 Jun 2006 00:15 GMT
> >> String str = "" + s1.charAt(0) + s1.charAt(5);
>
[quoted text clipped - 10 lines]
> String str =
>      new StringBuilder(s1.charAt(0)).append(s2.charAt(5)).toString();

This will create a StringBuilder of size : (int)(s1.charAt(0)).
Probably not what you want. The right way is:
new
StringBuilder().append(s1.charAt(0)).append(s2.charAt(5)).toString();

> You don't need to go through StringBuffer (or better StringBuilder) for
> something this simple.
>
> String str = String.valueOf(new char[] { s1.charAt(0), s1.charAt(5) });

How about:
String str = new String(new char[] { s1.charAt(0), s1.charAt(5) });

> Tom Hawtin
> --
> Unemployed English Java programmer
> http://jroller.com/page/tackline/
Thomas Hawtin - 09 Jun 2006 16:22 GMT
>> String str = String.valueOf(new char[] { s1.charAt(0), s1.charAt(5) });
>>
> How about:
> String str = new String(new char[] { s1.charAt(0), s1.charAt(5) });

I don't care whether I get a new string or a reused one. In my opinion,
it's better to give the library class the extra freedom.

I would go so far as to say that immutable classes should, in general,
not have public constructors.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Mike Schilling - 09 Jun 2006 01:33 GMT
>I spent hours trying to figure this out, so for others benifit, here it
> is:
[quoted text clipped - 9 lines]
>
> WTF?

char is actually an integral type, so, for instance

   'a' + 'b'

adds the unicode values for 'a' and 'b' and results in an int.  However, for
all types,

   String + anytype

converts the anytype to a String value and concatenates the two.  Thus your
solution

   "" + 'a' + 'b'

is effectively the same as

   "" + "a" + "b"

that is, "ab".

You could also use the String constructor:

   new String(new char[] { 'a', 'b'})

There are no other ways to perform this conversion directly [1].
(String)char seems logical, but isn't allowed.

1. That occur to me at the moment, anyway.
Chris Uppal - 09 Jun 2006 10:29 GMT
> There are no other ways to perform this conversion directly [1].
> (String)char seems logical, but isn't allowed.

One could write a utility function or two; something like (untested):

class StringUtils
{
   public static String
   concatenate(Object... args)
   {
       StringBuilder builder = new StringBuilder();
       for (Object arg : args)
           builder.append(arg);
       return builder.toString();
   }

   public static String
   concatenateWithSeparator(Object separator, Object... args)
   {
       StringBuilder builder = new StringBuilder();
       for (Object arg : args)
       {
           if (builder.length() > 0)
               builder.append(separator);
           builder.append(arg);
       }
       return builder.toString();
   }
}

(It would be nice if we were allowed to use ... for arguments before the last
one -- this isn't C, there's no technical reason why the compiler couldn't sort
it out.)

   -- chris
Dimitri Maziuk - 09 Jun 2006 17:45 GMT
Mike Schilling sez:

>>I spent hours trying to figure this out, so for others benifit, here it
>> is:
[quoted text clipped - 38 lines]
>
> 1. That occur to me at the moment, anyway.

s1.substring( 0, 1 ) + s1.substring( 5, 6 )

A dumb compiler would presumably create 3.1 transient strings
for
 "" + s.charAt( i ) + s.charAt( j )
(.1 because "" would be interned and created at startup).

 s.substring( i, i+1 ) + s.substring( j, j+1 )
would only create 2 transients.

Rumour has it, a smart compiler can optimize transients away,
the question is how smart is "smart". My guess would be that
it will work for .substring() version and likely won't work
for .charAt() version (unless the optimizer can look past the
return value of charAt() and notice we're actually pulling out
substrings).

The bulletproof way is, of course, appending to StringBuilder
as suggested upthread: you get a single transient (and much
"lighter") buffer instead of 2+ transient strings.

Dima
Signature

Politics and religion are just like software and hardware. They all suck, the
documentation is provably incorrect, and all the vendors tell lies.
                                                           -- Andrew Dalgleish

Thomas Hawtin - 09 Jun 2006 18:45 GMT
> s1.substring( 0, 1 ) + s1.substring( 5, 6 )
>
[quoted text clipped - 5 lines]
>   s.substring( i, i+1 ) + s.substring( j, j+1 )
> would only create 2 transients.

It's worse than that, there are StringBuilders about. I have no idea why
javac produces such bad code, but that is what it does. See below.

For a more reasonable use of substring, use String.concat rather than
letting the compiler louse it up:

  str.substring(i, i+1).concat(str.substring(j, j+1))

That, I believe, only produces two temporary String objects (but no
extra char[]s). String.valuOf(char[]) just creates one temporary char[].
StringBuilder will create a temporary StringBuilder object and an
oversized (a little) char[].

> Rumour has it, a smart compiler can optimize transients away,
> the question is how smart is "smart". My guess would be that
> it will work for .substring() version and likely won't work
> for .charAt() version (unless the optimizer can look past the
> return value of charAt() and notice we're actually pulling out
> substrings).

It looks as if one of the Sun 1.6 fcs byte -> machine code compilers
will be able to do the analysis (at least if you use
-XX:+DoEscapeAnalysis) but does not do stack allocation.

However, allocating short lived objects is surprisingly cheap.

> The bulletproof way is, of course, appending to StringBuilder
> as suggested upthread: you get a single transient (and much
> "lighter") buffer instead of 2+ transient strings.

Strings will share the char[]. So it's creating a StringBuilder plus
char[] vs two Strings (and *no* temporary char[]s).

Of course, it all depends upon the implementation used.

Tom Hawtin

class X {
    String fn(String str, int i, int j) {
        return str.substring(i, i+1) + str.substring(j, j+1);
    }
}

$ javap -c X
Compiled from "X.java"
class X extends java.lang.Object{
X();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

java.lang.String fn(java.lang.String, int, int);
  Code:
   0:   new     #2; //class java/lang/StringBuilder
   3:   dup
   4:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
   7:   aload_1
   8:   iload_2
   9:   iload_2
   10:  iconst_1
   11:  iadd
   12:  invokevirtual   #4; //Method
java/lang/String.substring:(II)Ljava/lang/String;
   15:  invokevirtual   #5; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   18:  aload_1
   19:  iload_3
   20:  iload_3
   21:  iconst_1
   22:  iadd
   23:  invokevirtual   #4; //Method
java/lang/String.substring:(II)Ljava/lang/String;
   26:  invokevirtual   #5; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   29:  invokevirtual   #6; //Method
java/lang/StringBuilder.toString:()Ljava/lang/String;
   32:  areturn

}
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Jussi Piitulainen - 09 Jun 2006 20:01 GMT
> A dumb compiler would presumably create 3.1 transient strings
> for
[quoted text clipped - 3 lines]
>   s.substring( i, i+1 ) + s.substring( j, j+1 )
> would only create 2 transients.

I thought the first one was specified to be equivalent to

   new StringBuffer()
     .append("")
     .append(s.charAt(i))
     .append(s.charAt(j))
     .toString(),

or maybe it's a StringBuilder nowadays. Why would even a dumb compiler
produce worse code?
Oliver Wong - 09 Jun 2006 21:12 GMT
>> A dumb compiler would presumably create 3.1 transient strings
>> for
[quoted text clipped - 14 lines]
> or maybe it's a StringBuilder nowadays. Why would even a dumb compiler
> produce worse code?

   Perhaps because it depends on knowledge of the API. It might be
occasionally be desirable to run a Java program without any of Sun's API
available. If the compiler produced code using StringBuffer, the JVM might
report a "StringBuffer class not found", despite the fact that the original
source code never mentions StringBuffer.

   - Oliver
Mike Schilling - 09 Jun 2006 21:32 GMT
>>> A dumb compiler would presumably create 3.1 transient strings
>>> for
[quoted text clipped - 20 lines]
> report a "StringBuffer class not found", despite the fact that the
> original source code never mentions StringBuffer.

If the core java.xxx classes aren't present, it isn't Java.  StringBuffer is
no less part of Java than String, Object, or Exception (or int and boolean,
for that matter.)
Jussi Piitulainen - 09 Jun 2006 21:45 GMT
>>> A dumb compiler would presumably create 3.1 transient strings
>>> for
[quoted text clipped - 20 lines]
> JVM might report a "StringBuffer class not found", despite the fact
> that the original source code never mentions StringBuffer.

I think it would need to have something equivalent internally anyway,
to implement string concatenation.

And wouldn't it then throw ClassNotFound on String when creating those
excess strings? I don't quite believe in the scenario.
Oliver Wong - 12 Jun 2006 16:14 GMT
>> Why would even a dumb compiler
>> produce worse code?
>
>    Perhaps because it depends on knowledge of the API. It might be
> occasionally be desirable to run a Java program without any of Sun's API
> available. If the compiler produced code using StringBuffer
[obviously, I meant String instead of StringBuffer here]
> , the JVM might report a "StringBuffer class not found", despite the fact
> that the original source code never mentions StringBuffer.

   I mentioned this mainly because in this competition I had entered for
writing an optimizing Java compiler, I had taken advantage of the fact that
I knew the behaviour of the StringBuffer class to replace certain calls with
others. If I recall correctly, it was something like changing this:

<pseudo bytecode>
invoke 0 parameter constructor of StringBuffer.
dup
push "Foo"
invoke 1 parameter append method.
dup
push "Bar"
invoke 1 parameter append method.
invoke 0 parameter toString
</pseudo bytecode>

to this:

<pseudo bytecode>
push "Foo"
invoke 1 parameter constructor of StringBuffer.
dup
push "Bar"
invoke 1 parameter append method.
invoke 0 parameter toString
</pseudo bytecode>

and the judges said I shouldn't have relied on information on the
semantics/behaviour of the API, but they let it slide for this competition
anyway.

   - Oliver
Mike Schilling - 12 Jun 2006 20:53 GMT
>>> Why would even a dumb compiler
>>> produce worse code?
[quoted text clipped - 36 lines]
> and the judges said I shouldn't have relied on information on the
> semantics/behaviour of the API,

Uh-huh.  It's OK to use one constructor and the append method, but using a
different constructor is cheating.  What had they been smoking?

> but they let it slide for this competition anyway.
Dale King - 05 Jul 2006 08:44 GMT
>>> Why would even a dumb compiler
>>> produce worse code?
[quoted text clipped - 37 lines]
> semantics/behaviour of the API, but they let it slide for this
> competition anyway.

I remember that the Eclipse compiler generated code like the second one
and the code generated ran much slower. I found the link to the thread:

http://dev.eclipse.org/newslists/news.eclipse.tools/msg29599.html

And in particular this message of mine:

http://dev.eclipse.org/newslists/news.eclipse.tools/msg30054.html

Signature

 Dale King

Tony - 09 Jun 2006 09:25 GMT
> I spent hours trying to figure this out, so for others benifit, here it
> is:
[quoted text clipped - 11 lines]
> Anyway, there you have it.
> -Mike

1. char is actually of type integer as mentioned by earlier replier
2. Maybe you can solve like this:
   String str  = String.valueOf(s1.charAt(0)) +
String.valueOf(s1.charAt(5));


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.