Easiest way to create a string with n times character 'x'?

A

Arnold Peters

Assume I want to create a string of length n which contains n times the character 'x'.
How do I implement this the easiest way? n could vary from function time to time.

Ok. I could code

char mychar = 'x';
String tmp = "";
for (int i=1; i<n; i++)
tmp = tmp + String(mychar);

But this is very (!) inefficient.

Other solution would be:

String ressource = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
String tmp = ressource.subsctring(0,n);

But this is inefficient too and requires a a priori determination of the maximum possible
length;

As far as I know there is a function similar to

String tmp = makeString('x',n);

but I don't remember the exact name.
Can somehelp give me a hint?

Arni
 
J

Joona I Palaste

Arnold Peters <[email protected]> scribbled the following
Assume I want to create a string of length n which contains n times the character 'x'.
How do I implement this the easiest way? n could vary from function time to time.
Ok. I could code
char mychar = 'x';
String tmp = "";
for (int i=1; i<n; i++)
tmp = tmp + String(mychar);

But this is very (!) inefficient.
Other solution would be:
String ressource = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
String tmp = ressource.subsctring(0,n);
But this is inefficient too and requires a a priori determination of the maximum possible
length;
As far as I know there is a function similar to
String tmp = makeString('x',n);
but I don't remember the exact name.
Can somehelp give me a hint?

A slightly varied solution from your first one.
StringBuffer buf = new StringBuffer();
for (int i=1; i<n; i++) {
buf.append(mychar);
}
tmp = buf.toString();
This does pretty much the same thing as your first solution but skips
the creating of intermediary String objects. Should be at least twice
as efficient.
 
T

Thomas Kellerer

Joona I Palaste wrote on 27.01.2005 21:42:
A slightly varied solution from your first one.
StringBuffer buf = new StringBuffer();
for (int i=1; i<n; i++) {
buf.append(mychar);
}
tmp = buf.toString();
This does pretty much the same thing as your first solution but skips
the creating of intermediary String objects. Should be at least twice
as efficient.
Even faster (because it's not synchronized:


char[] buffer = new char[size];
for (int i=0; i < size; i++)
{
buffer = c;
}
tmp = new String(buffer);
 
F

Fred

char[] buffer = new char[size];
Doing this also suffers from the need to know the maxmium size of the
string beforehand.

The StringBuffer solution above would work without needing this
information. Additionally, an enhancing modification would be:

StringBuffer buf = new StringBuffer();
synchronized( buf ) {
for (int i=1; i<n; i++) {
buf.append(mychar);
}
}

This would eliminate the need to capture the lock on "buf" everytime
..append() is called.

If this procedure does not have to be synchronized (or guaranteed to be
thread safe), investigate using the StringBuilder class. This requires
Java 1.5 but will not introduce the synchronization overhead of the
StringBuffer class.
 
T

Thomas Kellerer

char[] buffer = new char[size];
Doing this also suffers from the need to know the maxmium size of the
string beforehand.

Why?

StringBuffer buf = new StringBuffer();
synchronized( buf ) {
for (int i=1; i<n; i++) {
buf.append(mychar);
}
}

The usage of n here is exactly the same as with new char[n] I cannot see a
difference.

I find the usage of the synchronized keyword there interesting. Are you saying
that the JVM will not synchronize the call to append() if it's called in a
synchronized block?

Regards
Thomas
 
J

Jesper Nordenberg

Thomas Kellerer said:
I find the usage of the synchronized keyword there interesting. Are you saying
that the JVM will not synchronize the call to append() if it's called in a
synchronized block?

If the append() method synchronizes on the StringBuffer object (which
I believe it does) there would be some gains if it's faster to check a
lock you already have than to acquire and release it, and the Hotspot
compiler doesn't eliminate the lock/unlock code completely because the
StringBuffer object never escapes the method and therefore can't be
accessed by other threads.

/Jesper Nordenberg
 
T

Thomas Kellerer

char[] buffer = new char[size];
Doing this also suffers from the need to know the maxmium size of the
string beforehand.

I did some timings on the different solutions using the following program

public class Test
{
public static String fillString1(int size, char c)
{
StringBuffer b = new StringBuffer(size);
for (int i=0; i < size; i++)
{
b.append(c);
}
return b.toString();
}

public static String fillString2(int size, char c)
{
StringBuffer b = new StringBuffer(size);
synchronized (b)
{
for (int i=0; i < size; i++)
{
b.append(c);
}
}
return b.toString();
}

public static String fillString3(int size, char c)
{
char[] b = new char[size];
for (int i=0; i < size; i++)
{
b = c;
}
return new String(b);
}

public static void main(String[] args)
{
long start, end;
int count = 500000;
int size = 50;
char c = 'x';

start = System.currentTimeMillis();
for (int i=0; i < count; i++)
{
String s = fillString1(size, c);
}
end = System.currentTimeMillis();
System.out.println("time1: " + (end - start));

start = System.currentTimeMillis();
for (int i=0; i < count; i++)
{
String s = fillString2(size, c);
}
end = System.currentTimeMillis();
System.out.println("time2: " + (end - start));

start = System.currentTimeMillis();
for (int i=0; i < count; i++)
{
String s = fillString3(size, c);
}
end = System.currentTimeMillis();
System.out.println("time3: " + (end - start));
}
}

On my computer the version with the char[] is significantly faster then the
StringBuffer version:

time1: 1953
time2: 1462
time3: 330

It doesn't change too much when increasing the size of the generated string
(simply play around with the size parameter)

So the synchronization trick actually shows some performance gain.


Regards
Thomas
 
T

Thomas Kellerer

Interesting. Which JVM do your numbers apply to ?
Running on Windows XP:

Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03)
Java HotSpot(TM) Client VM (build 1.4.2_06-b03, mixed mode)

The timing with Sun's JDK 1.5.0 is nearly the same.

Thomas
 
F

Fred

Thomas said:
char[] buffer = new char[size];
Doing this also suffers from the need to know the maxmium size of the
string beforehand.

Why?

StringBuffer buf = new StringBuffer();
synchronized( buf ) {
for (int i=1; i<n; i++) {
buf.append(mychar);
}
}

The usage of n here is exactly the same as with new char[n] I cannot see a
difference.

I find the usage of the synchronized keyword there interesting. Are you saying
that the JVM will not synchronize the call to append() if it's called in a
synchronized block?

Regards
Thomas
char[] buffer = new char[size];
Doing this also suffers from the need to know the maxmium size of the
string beforehand.

Why?

Because the value of "size" isn't going to be assigned
nondeterministically.
 
T

Thomas Fritsch

Thomas said:
Joona I Palaste wrote on 27.01.2005 21:42:
A slightly varied solution from your first one.
StringBuffer buf = new StringBuffer();
for (int i=1; i<n; i++) {
buf.append(mychar);
}
tmp = buf.toString();
This does pretty much the same thing as your first solution but skips
the creating of intermediary String objects. Should be at least twice
as efficient.

Even faster (because it's not synchronized:


char[] buffer = new char[size];
for (int i=0; i < size; i++)
{
buffer = c;
}
tmp = new String(buffer);


Even easier, and as fast as the above:

char[] buffer = new char[size];
Arrays.fill(buffer, c);
tmp = new String(buffer);
 

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,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top