111

I did check the other questions; this question has its focus on solving this particular question the most efficient way.

Sometimes you want to create a new string with a specified length, and with a default character filling the entire string.

ie, it would be cool if you could do new String(10, '*') and create a new String from there, with a length of 10 characters all having a *.

Because such a constructor does not exist, and you cannot extend from String, you have either to create a wrapper class or a method to do this for you.

At this moment I am using this:

protected String getStringWithLengthAndFilledWithCharacter(int length, char charToFill) {
    char[] array = new char[length];
    int pos = 0;
    while (pos < length) {
        array[pos] = charToFill;
        pos++;
    }
    return new String(array);
}

It still lacks any checking (ie, when length is 0 it will not work). I am constructing the array first because I believe it is faster than using string concatination or using a StringBuffer to do so.

Anyone else has a better sollution?

Stephen Denne
  • 36,219
  • 10
  • 45
  • 60
Stefan Hendriks
  • 4,705
  • 5
  • 34
  • 43

16 Answers16

156

Apache Commons Lang (probably useful enough to be on the classpath of any non-trivial project) has StringUtils.repeat():

String filled = StringUtils.repeat("*", 10);

Easy!

Michael Schmeißer
  • 3,407
  • 1
  • 19
  • 32
Cowan
  • 37,227
  • 11
  • 66
  • 65
  • 3
    This should be the topvoted answer. Thanks ;) – lmo Oct 21 '15 at 12:56
  • 4
    This is the best answer. The current top answer uses leftpad in an unintuitive way to do something it wasn't really intended to do, which makes it harder to understand what's supposed to happen. This answer self-documents better. – Benjamin Aug 01 '16 at 17:04
  • 1
    @Benjamin i agree and marked this as the 'real' answer :) – Stefan Hendriks May 07 '18 at 10:27
111

Simply use the StringUtils class from apache commons lang project. You have a leftPad method:

StringUtils.leftPad("foobar", 10, '*'); // Returns "****foobar"
Romain Linsolas
  • 79,475
  • 49
  • 202
  • 273
  • 3
    +1 - that's exactly what he was looking for (aka 'cool'). For the exact same behaviour, but that's obvious, do: `StringUtils.leftPad("", 10, '*');` – Andreas Dolk Nov 26 '09 at 10:47
  • 3
    +1 nice solution, though I wouldn't add a jar to my project just for that. – abyx Nov 26 '09 at 10:53
  • Thanks. Yes that looks like a more suitable way to use it. Luckily I am already using this jar, so i could use this straight away. – Stefan Hendriks Nov 26 '09 at 10:58
  • 10
    Or use repeat(), which doesn't require the empty string at the start and is arguably clearer in intent (see my answer) – Cowan Nov 26 '09 at 11:03
  • @abyx> Yes, you will need to add a JAR, but commons lang offers so nice utils methods, so I don't think it is really a drawback! – Romain Linsolas Nov 26 '09 at 12:30
  • 1
    Over 300kb for this jar?? Yuck, no thanks. Not for a mobile app. No need for bloatware. – Johann Jul 19 '13 at 13:06
65

No need to do the loop, and using just standard Java library classes:

protected String getStringWithLengthAndFilledWithCharacter(int length, char charToFill) {
  if (length > 0) {
    char[] array = new char[length];
    Arrays.fill(array, charToFill);
    return new String(array);
  }
  return "";
}

As you can see, I also added suitable code for the length == 0 case.

unwind
  • 391,730
  • 64
  • 469
  • 606
44

Some possible solutions.

This creates a String with length-times '0' filled and replaces then the '0' with the charToFill (old school).

String s = String.format("%0" + length + "d", 0).replace('0', charToFill);

This creates a List containing length-times Strings with charToFill and then joining the List into a String.

String s = String.join("", Collections.nCopies(length, String.valueOf(charToFill)));

This creates a unlimited java8 Stream with Strings with charToFill, limits the output to length and collects the results with a String joiner (new school).

String s = Stream.generate(() -> String.valueOf(charToFill)).limit(length).collect(Collectors.joining());
kwarnke
  • 1,424
  • 1
  • 15
  • 10
41

In Java 11, you have repeat:

String s = " ";
s = s.repeat(1);

(Although at the time of writing still subject to change)

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
26
char[] chars = new char[10];
Arrays.fill(chars, '*');
String text = new String(chars);
Pavel Netesa
  • 2,092
  • 1
  • 16
  • 11
9

To improve performance you could have a single predefined sting if you know the max length like:

String template = "####################################";

And then simply perform a substring once you know the length.

Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98
Karl
  • 2,927
  • 8
  • 31
  • 39
  • 2
    +1: I just read on another post that substring creates a String that just uses the same char[] of the original String. So it's an O(1) operation (no loop) and it saves memory (if that is a real issue) – Andreas Dolk Nov 26 '09 at 12:20
7

Solution using Google Guava

String filled = Strings.repeat("*", 10);
javacavaj
  • 2,901
  • 5
  • 39
  • 66
6
public static String fillString(int count,char c) {
    StringBuilder sb = new StringBuilder( count );
    for( int i=0; i<count; i++ ) {
        sb.append( c ); 
    }
    return sb.toString();
}

What is wrong?

4

The above is fine. Do you mind if I ask you a question - Is this causing you a problem? It seams to me you are optimizing before you know if you need to.

Now for my over engineered solution. In many (thou not all) cases you can use CharSequence instead of a String.

public class OneCharSequence implements CharSequence {
  private final char value;
  private final int length;
  public OneCharSequence(final char value, final int length) {
    this.value = value;
    this.length = length;
  }
  public char   charAt(int index)  {
     if(index < length) return value;
     throw new IndexOutOfBoundsException();
  }
  public int length() {
    return length;
  }
  public CharSequence subSequence(int start, int end) {
     return new OneCharSequence(value, (end-start));
  }
  public String toString() {
    char[] array = new char[length];
    Arrays.fill(array, value);
    return new String(array);
  }
}
Michael Lloyd Lee mlk
  • 14,561
  • 3
  • 44
  • 81
4

using Dollar is simple:

String filled = $("=").repeat(10).toString(); // produces "=========="
MrLore
  • 3,759
  • 2
  • 28
  • 36
dfa
  • 114,442
  • 31
  • 189
  • 228
4

Solution using Google Guava, since I prefer it to Apache Commons-Lang:

/**
 * Returns a String with exactly the given length composed entirely of
 * the given character.
 * @param length the length of the returned string
 * @param c the character to fill the String with
 */
public static String stringOfLength(final int length, final char c)
{
    return Strings.padEnd("", length, c);
}
David
  • 1,157
  • 2
  • 12
  • 19
2

Try this Using the substring(int start, int end); method

String myLongString = "abcdefghij";
if (myLongString .length() >= 10)
String shortStr = myLongString.substring(0, 5)+ "...";

this will return abcde.

Qadir Hussain
  • 8,721
  • 13
  • 89
  • 124
2

One extra note: it seems that all public ways of creating a new String instance involves necessarily the copy of whatever buffer you are working with, be it a char[], a StringBuffer or a StringBuilder. From the String javadoc (and is repeated in the respective toString methods from the other classes):

The contents of the character array are copied; subsequent modification of the character array does not affect the newly created string.

So you'll end up having a possibly big memory copy operation after the "fast filling" of the array. The only solution that may avoid this issue is the one from @mlk, if you can manage working directly with the proposed CharSequence implementation (what may be the case).

PS: I would post this as a comment but I don't have enough reputation to do that yet.

Chuim
  • 1,983
  • 3
  • 17
  • 20
1

Mi solution :

  pw = "1321";
    if (pw.length() < 16){
      for(int x = pw.length() ; x < 16 ; x++){
        pw  += "*";
      }
    }

The output :

1321************
CodeNoob
  • 345
  • 4
  • 17
0

Try this jobber

String stringy =null;
 byte[] buffer =  new byte[100000];
            for (int i = 0; i < buffer.length; i++) {
            buffer[i] =0;

        }
            stringy =StringUtils.toAsciiString(buffer);
user1198289
  • 637
  • 1
  • 5
  • 14