Java-创建一个具有指定长度和特定字符填充的新 String 实例。最佳解决方案?

我确实检查了其他问题; 这个问题的重点是以最有效的方式解决这个特定的问题。

有时候,您希望创建一个具有指定长度的新字符串,并在整个字符串中填充一个默认字符。

也就是说,如果你可以使用 new String(10, '*')并从中创建一个新的 String,它的长度为10个字符,所有字符都有一个 * ,那就太酷了。

因为这样的构造函数不存在,而且您不能从 String 进行扩展,所以您必须创建一个包装器类或者一个方法来完成这项工作。

此时此刻,我正在使用这个:

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);
}

它仍然缺少任何检查(例如,当长度为0时,它将不工作)。我首先构建数组,因为我相信它比使用字符串连接或使用 StringBuffer 更快。

还有人有更好的解决办法吗?

197371 次浏览

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

StringUtils.leftPad("foobar", 10, '*'); // Returns "****foobar"

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.

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?

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.

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!

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);
}
}

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.

using Dollar is simple:

String filled = $("=").repeat(10).toString(); // produces "=========="

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.

char[] chars = new char[10];
Arrays.fill(chars, '*');
String text = new String(chars);

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);

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());

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);
}

Mi solution :

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

The output :

1321************

Solution using Google Guava

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

In Java 11, you have repeat:

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

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