create a string of <n> equal chars <c>

A

Andreas Leitgeb

It seems so basic that I can't believe such a feature wasn't in
the standard library:

- given two parameters (int n, char c), return a String that
consists of <n> copies of <c>
(would be imho best suited as a constructor of String itself)

or (what I'd actually need it for:)
- given a String, an int n and a char c, cut or pad(with c) the String
to length n. (the cut/padded one would be a new String, of course)
(I'd need it right-padded, but the problem is the same for left-
padding)

As I know that the strings I need it for are of limited length, and
only a few pad-chars are ever needed, I can help myself, by using
a String constant, like "............................" for each pad-
char, and use an appropriate .substring on it. This sure looks like
a crude hack, but the alternatives involving StringBuffer(*) and
char[n] don't seem much better.

*: StringBuffer.setLength only pads with \u0000, and there doesn't
seem to be an append(numCopies,padChar), either, so one seems
to be bound to adding the same char repeatedly in a loop.

Did I miss some simple idiom? I really hope so.
 
K

Kevin McMurtrie

Andreas Leitgeb said:
It seems so basic that I can't believe such a feature wasn't in
the standard library:

- given two parameters (int n, char c), return a String that
consists of <n> copies of <c>
(would be imho best suited as a constructor of String itself)

or (what I'd actually need it for:)
- given a String, an int n and a char c, cut or pad(with c) the String
to length n. (the cut/padded one would be a new String, of course)
(I'd need it right-padded, but the problem is the same for left-
padding)

As I know that the strings I need it for are of limited length, and
only a few pad-chars are ever needed, I can help myself, by using
a String constant, like "............................" for each pad-
char, and use an appropriate .substring on it. This sure looks like
a crude hack, but the alternatives involving StringBuffer(*) and
char[n] don't seem much better.

*: StringBuffer.setLength only pads with \u0000, and there doesn't
seem to be an append(numCopies,padChar), either, so one seems
to be bound to adding the same char repeatedly in a loop.

Did I miss some simple idiom? I really hope so.

Homework?

It's easy when the pad character is a constant:

static String padToDigits (final String s, final int digits)
{
final int len= s.length();
if (len > digits)
throw new IllegalArgumentException ("Input too long:" + s);
if (digits > 40)
throw new IllegalArgumentException ("Too many digits:" + digits);
if (len == digits)
return s;
return "0000000000000000000000000000000000000000"
.substring(0, digits - len) + s;
}

When it's not, a for loop to pad a StringBuidler works fine.
 
J

Jim Janney

Andreas Leitgeb said:
It seems so basic that I can't believe such a feature wasn't in
the standard library:

- given two parameters (int n, char c), return a String that
consists of <n> copies of <c>
(would be imho best suited as a constructor of String itself)

or (what I'd actually need it for:)
- given a String, an int n and a char c, cut or pad(with c) the String
to length n. (the cut/padded one would be a new String, of course)
(I'd need it right-padded, but the problem is the same for left-
padding)

As I know that the strings I need it for are of limited length, and
only a few pad-chars are ever needed, I can help myself, by using
a String constant, like "............................" for each pad-
char, and use an appropriate .substring on it. This sure looks like
a crude hack, but the alternatives involving StringBuffer(*) and
char[n] don't seem much better.

*: StringBuffer.setLength only pads with \u0000, and there doesn't
seem to be an append(numCopies,padChar), either, so one seems
to be bound to adding the same char repeatedly in a loop.

Did I miss some simple idiom? I really hope so.

http://commons.apache.org/lang/api-...ils.html#leftPad(java.lang.String, int, char)
 
A

Andreas Leitgeb

Kevin McMurtrie said:
Andreas Leitgeb said:
It seems so basic that I can't believe such a feature wasn't in
the standard library:
or (what I'd actually need it for:)
- given a String, an int n and a char c, cut or pad(with c) the String
to length n. (the cut/padded one would be a new String, of course)
(I'd need it right-padded, but the problem is the same for left-
padding)
As I know that the strings I need it for are of limited length, and
only a few pad-chars are ever needed, I can help myself, by using
a String constant, like "............................" for each pad-
char, and use an appropriate .substring on it. This sure looks like
a crude hack, but the alternatives involving StringBuffer(*) and
char[n] don't seem much better.
It's easy when the pad character is a constant:

My request was for a *simple* idiom. I explicitly wrote that I did
know about using .substring() on a constant string and called it a crude
hack (for its imposed limit on n and c).
When it's not, a for loop to pad a StringBuidler works fine.

That's one of the other strategies I mentioned as not much better.

Thanks for trying to help, but that didn't yet.
 
E

Eric Sosman

Kevin McMurtrie said:
Andreas Leitgeb said:
It seems so basic that I can't believe such a feature wasn't in
the standard library:
or (what I'd actually need it for:)
- given a String, an int n and a char c, cut or pad(with c) the String
to length n. (the cut/padded one would be a new String, of course)
(I'd need it right-padded, but the problem is the same for left-
padding)
As I know that the strings I need it for are of limited length, and
only a few pad-chars are ever needed, I can help myself, by using
a String constant, like "............................" for each pad-
char, and use an appropriate .substring on it. This sure looks like
a crude hack, but the alternatives involving StringBuffer(*) and
char[n] don't seem much better.

One easy way to write "the appropriate substring" is to
concatenate and *then* cut:

String padded = (original + padChars).substring(0, n);

This costs two String creations instead of (at most) one, but is
certainly less verbose than

String padded = (original.length() < n)
? original + padChars.substring(0, n-original.length())
: original.substring(0, n);

As for finding anything simpler that's built-in ... Well, there
*might* be some way to use String.format() to do it -- but there's
a saying "Don't use a cannon to kill a canary," and .format() looks
quite a lot like a cannon here ...
 
L

Lew

Eric said:
-- but there's a saying "Don't use a cannon to kill a canary," ...

Unless it's a REALLY big canary.

Q: What does a 500-pound (227-kg) canary say?

A: *CHIRP*!!
 
A

Andreas Leitgeb

Eric Sosman said:
Kevin McMurtrie said:
It seems so basic that I can't believe such a feature wasn't in
the standard library:
- given a String, an int n and a char c, cut or pad(with c) the String
to length n. (the cut/padded one would be a new String, of course)
(I'd need it right-padded, but the problem is the same for left-
padding)
As I know that the strings I need it for are of limited length, and
only a few pad-chars are ever needed, I can help myself, by using
a String constant, like "............................" for each pad-
char, and use an appropriate .substring on it. This sure looks like
a crude hack, but the alternatives involving StringBuffer(*) and
char[n] don't seem much better.

One easy way to write "the appropriate substring" is to
concatenate and *then* cut:
String padded = (original + padChars).substring(0, n);

Yep, of course. I'd choose the latter one, if I got round to create a
helper method for that task, but use the former if I just inline it
somewhere.
But one would still need to decide on the maximum length beforehand.
String padded = (original.length() < n)
? original + padChars.substring(0, n-original.length())
: original.substring(0, n);
As for finding anything simpler that's built-in ... Well, there
*might* be some way to use String.format() to do it -- but there's
a saying "Don't use a cannon to kill a canary," and .format() looks
quite a lot like a cannon here ...
Indeed :)
So would
new String(new char[n]).replace('\0',ch), creating two extra objects.
And
char[] tmp=new char[n]; java.util.Arrays.fill(tmp,ch); ...= new String(tmp);
(why does Arrays.fill not return a ref to it's argument?)

A more elaborate, but likely not really paying approach: :)

public class BoringString implements CharSequence {
private char m_ch; private int m_len;
public BoringString(int len, char ch) { m_ch=ch; m_len=len; }
public char charAt(int index) { return m_ch; }
public int length() { return m_len; }
public BoringString subSequence(int start, int end) {
return new BoringString(end-start,m_ch);
}
public String toString() {
return new StringBuilder(this).toString();
} // that seems to work: SB doesn't use toString() on its arg.
}

PS: At least the apache-people thought of rightPad(String,int,char)
 
A

Arne Vajhøj

It seems so basic that I can't believe such a feature wasn't in
the standard library:

- given two parameters (int n, char c), return a String that
consists of<n> copies of<c>
(would be imho best suited as a constructor of String itself)

or (what I'd actually need it for:)
- given a String, an int n and a char c, cut or pad(with c) the String
to length n. (the cut/padded one would be a new String, of course)
(I'd need it right-padded, but the problem is the same for left-
padding)

As I know that the strings I need it for are of limited length, and
only a few pad-chars are ever needed, I can help myself, by using
a String constant, like "............................" for each pad-
char, and use an appropriate .substring on it. This sure looks like
a crude hack, but the alternatives involving StringBuffer(*) and
char[n] don't seem much better.

*: StringBuffer.setLength only pads with \u0000, and there doesn't
seem to be an append(numCopies,padChar), either, so one seems
to be bound to adding the same char repeatedly in a loop.

Did I miss some simple idiom? I really hope so.

I don't think so.

Apparently they forgot about this useful feature.

Arne
 
R

Roedy Green

It seems so basic that I can't believe such a feature wasn't in
the standard library:

it is part of the common11 tools for JDK 1.1+
http://mindprod.com/products1.html#COMMON11

The method is called StringTools.rep

/**
* Produce a String of a given repeating character.
*
* @param c the character to repeat
* @param count the number of times to repeat
*
* @return String, e.g. rep('*',4) returns "****"
* @noinspection WeakerAccess,SameParameterValue
*/
public static String rep( char c, int count )
{
if ( c == ' ' && count <= SOMESPACES.length() )
{
return SOMESPACES.substring( 0, count );
}
char[] s = new char[count];
for ( int i = 0; i < count; i++ )
{
s[ i ] = c;
}
return new String( s ).intern();
}

/**
* used to efficiently generate Strings of spaces of varying
length
*/
private static final String SOMESPACES = " ";
 
V

voorth

How about using Arrays.fill() ?

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


It seems so basic that I can't believe such a feature wasn't in
the standard library:

it is part of the common11 tools for JDK 1.1+http://mindprod.com/products1.html#COMMON11

The method is called StringTools.rep

 /**
     * Produce a String of a given repeating character.
     *
     * @param c     the character to repeat
     * @param count the number of times to repeat
     *
     * @return String, e.g. rep('*',4) returns "****"
     * @noinspection WeakerAccess,SameParameterValue
     */
    public static String rep( char c, int count )
        {
        if ( c == ' ' && count <= SOMESPACES.length() )
            {
            return SOMESPACES.substring( 0, count );
            }
        char[] s = new char[count];
        for ( int i = 0; i < count; i++ )
            {
            s[ i ] = c;
            }
        return new String( s ).intern();
        }

   /**
     * used to efficiently generate Strings of spaces of varying
length
     */
    private static final String SOMESPACES = " ";
 
K

Kevin McMurtrie

Roedy Green said:
It seems so basic that I can't believe such a feature wasn't in
the standard library:

it is part of the common11 tools for JDK 1.1+
http://mindprod.com/products1.html#COMMON11

The method is called StringTools.rep

/**
* Produce a String of a given repeating character.
*
* @param c the character to repeat
* @param count the number of times to repeat
*
* @return String, e.g. rep('*',4) returns "****"
* @noinspection WeakerAccess,SameParameterValue
*/
public static String rep( char c, int count )
{
if ( c == ' ' && count <= SOMESPACES.length() )
{
return SOMESPACES.substring( 0, count );
}
char[] s = new char[count];
for ( int i = 0; i < count; i++ )
{
s[ i ] = c;
}
return new String( s ).intern();
}

/**
* used to efficiently generate Strings of spaces of varying
length
*/
private static final String SOMESPACES = " ";

Why use intern() on the second case? It's has always been undocumented
where the pool storage is and what the cost of using it is. The only
time I use that method is when generating keys for a Properties class.
 
T

Tom Anderson

As for finding anything simpler that's built-in ... Well, there *might*
be some way to use String.format() to do it -- but there's a saying
"Don't use a cannon to kill a canary," and .format() looks quite a lot
like a cannon here ...

I thought the traditional way to kill canaries was the throw them down
coalmines.

tom
 
D

Daniel Pitts

Roedy Green said:
It seems so basic that I can't believe such a feature wasn't in
the standard library:

it is part of the common11 tools for JDK 1.1+
http://mindprod.com/products1.html#COMMON11

The method is called StringTools.rep

/**
* Produce a String of a given repeating character.
*
* @param c the character to repeat
* @param count the number of times to repeat
*
* @return String, e.g. rep('*',4) returns "****"
* @noinspection WeakerAccess,SameParameterValue
*/
public static String rep( char c, int count )
{
if ( c == ' '&& count<= SOMESPACES.length() )
{
return SOMESPACES.substring( 0, count );
}
char[] s = new char[count];
for ( int i = 0; i< count; i++ )
{
s[ i ] = c;
}
return new String( s ).intern();
}

/**
* used to efficiently generate Strings of spaces of varying
length
*/
private static final String SOMESPACES = " ";

Why use intern() on the second case? It's has always been undocumented
where the pool storage is and what the cost of using it is. The only
time I use that method is when generating keys for a Properties class.
Why even use it there? I don't think I've ever seen a legitimate case
for using intern(). The *closest* I've seen to a valid use is someone
wanted to use it for synchronization based on a String key.
 
T

Tom Anderson

My rant was about the Java Standard Library

The standard library is already freak huge. If it had every item which
anyone couldn't believe wasn't in the standard library, it could be a very
leviathan, a behemoth, a colossus of codes.

What i think we could do with is a sort of Greater Standard Library. Some
way of giving certain packages official blessing, so that if you built
code on top of them, you'd have a reasonable expectation that someone out
there who wanted to run your code would already have them. This already
exists de facto for certain things - log4j, quite a bit of Apache Commons,
JUnit, and so on, but it could be useful to put it on a more formal,
although not completely formal, basis. We could tie this up with a process
for merging different libraries approaching the same problem, reviewing
and improving and integrating things, etc. We would end up with something
like a more comprehensive standard library, but without the mandarins at
Sunacle (or JCP Towers - shudder) having to decree it.

Not that i'm volunteering to organise this, of course.

tom
 
A

Arne Vajhøj

The standard library is already freak huge. If it had every item which
anyone couldn't believe wasn't in the standard library, it could be a
very leviathan, a behemoth, a colossus of codes.

But this is very basic functionality.

..NET has it.

C++ STL has it.

Python has it.

Ruby has it.

Arne
 
S

Stefan Ram

Arne Vajhøj said:
But this is very basic functionality.

Perl even has an own operator for it ('a' x 3 - or so),
but BASIC does not have anything like it - I don't know
about Common Lisp, Haskell, or Smalltalk in this regard.

One might ask the OP in which context/case he needs this,
then more answers might be possible, such as solutions
solving his general problem, but not requiring this.
 
A

Andreas Leitgeb

Stefan Ram said:
One might ask the OP in which context/case he needs this,
then more answers might be possible, such as solutions
solving his general problem, but not requiring this.

The OP (me) did write, that he (I) got to it by the need of custom-char
padding some String to a given size.

I also wrote that my needs fortunately weren't all that general, so I got
by with a couple of stock pad-strings, of which I pick the needed one,
append it to the given string, and then do a .substring() on it. (it's
the chars '0' and '9' and a max len well below 20 *for my current needs*.

So, it's not a matter of "This missing feature impedes me at my attempts
to save the world". Anyway, it seems like a very basic building block.

Btw., it also took them till 1.6 to add the very useful Arrays.copyOf().
 
S

Stefan Ram

Andreas Leitgeb said:
I also wrote that my needs fortunately weren't all that general, so I got
by with a couple of stock pad-strings, of which I pick the needed one,
append it to the given string, and then do a .substring() on it. (it's
the chars '0' and '9' and a max len well below 20 *for my current needs*.

I can not come up with a better solution now, but would suggest
to hide this implementation behind an interface, so that you can
easily replace this implementation in all you projects, once this
is better supported in Java. Like,

interface/class MyStringUtils
{ /** Appends multiple copies of padCharacter to the source, so that
the result has lenght as its length when measured in Unicode code points. */
public java.lang.String pad
( java.lang.String source, java.lang.String padCharacter, int length );
... }

Then, go for the implementation that is most readable/maintainable first,
and only optimize it for run-time speed, /if/ this was shown to be
necessary.
 

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,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top