Java - 创建一个具有指定长度并填充特定字符的新String实例。最佳方案? [重复]

时间:2020-12-22 20:17:02

This question already has an answer here:

这个问题在这里已有答案:

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 *.

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

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.

因为这样的构造函数不存在,并且您无法从String扩展,所以您要么创建一个包装类,要么为您执行此操作的方法。

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.

它仍然没有任何检查(即,当长度为0时,它将不起作用)。我首先构造数组,因为我相信它比使用字符串连接或使用StringBuffer更快。

Anyone else has a better sollution?

其他人有更好的解决方案吗?

17 个解决方案

#1


74  

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

Apache Commons Lang(可能对任何非平凡项目的类路径都很有用)具有StringUtils.repeat():

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

Easy!

简单!

#2


99  

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

只需使用apache commons lang项目中的StringUtils类。你有一个leftPad方法:

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

#3


52  

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

无需执行循环,只使用标准Java库类:

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.

如您所见,我还为长度== 0的情况添加了合适的代码。

#4


28  

Some possible solutions.

一些可能的解决方

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

这将创建一个填充长度为“0”的字符串,然后使用charToFill(旧学校)替换“0”。

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.

这将创建一个List,其中包含使用charToFill的长度字符串,然后将List连接到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).

这将使用charToFill创建带有字符串的无限java8 Stream,将输出限制为length并使用String joiner(新学校)收集结果。

String s = Stream.generate(() -> String.valueOf(charToFill)).limit(length).collect(Collectors.joining());

#5


16  

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

#6


6  

Solution using Google Guava

使用Google Guava的解决方案

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

#7


5  

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?

哪里不对?

#8


5  

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

为了提高性能,如果您知道最大长度,则可以使用单个预定义的sting:

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

String template =“####################################”;

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

然后在知道长度后简单地执行子串。

#9


4  

using Dollar is simple:

使用Dollar很简单:

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

#10


4  

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

使用Google Guava的解决方案,因为我更喜欢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);
}

#11


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.

现在为我的工程解决方案。在许多(不是全部)情况下,您可以使用CharSequence而不是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);
  }
}

#12


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

另外需要注意的是:似乎所有创建新String实例的公共方法都必然包含您正在使用的任何缓冲区的副本,无论是char [],StringBuffer还是StringBuilder。从String javadoc(并在其他类的相应toString方法中重复):

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

因此,在“快速填充”数组之后,您最终会有一个可能很大的内存复制操作。可以避免此问题的唯一解决方案是来自@mlk的解决方案,如果您可以管理直接使用建议的CharSequence实现(可能是这种情况)。

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

PS:我会将此作为评论发布,但我还没有足够的声誉来做到这一点。

#13


1  

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

试试这个使用substring(int start,int end);方法

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

this will return abcde.

这将返回abcde。

#14


1  

Mi solution :

米解决方案:

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

The output :

输出 :

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

#15


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

#16


0  

You can use a while loop like this:

您可以像这样使用while循环:

String text = "Hello";
while (text.length() < 10) { text += "*"; }
System.out.println(text);

Will give you:

会给你:

Hello*****

Or get the same result with a custom method:

或者使用自定义方法获得相同的结果:

    public static String extendString(String text, String symbol, Integer len) {
        while (text.length() < len) { text += symbol; }
        return text;
    }

Then just call:

然后打电话:

extendString("Hello", "*", 10)

It may also be a good idea to set a length check to prevent infinite loop.

设置长度检查以防止无限循环也是一个好主意。

#17


0  

In Java 11, you have repeat:

在Java 11中,您重复:

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

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

(虽然在撰写本文时仍有待更改)

#1


74  

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

Apache Commons Lang(可能对任何非平凡项目的类路径都很有用)具有StringUtils.repeat():

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

Easy!

简单!

#2


99  

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

只需使用apache commons lang项目中的StringUtils类。你有一个leftPad方法:

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

#3


52  

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

无需执行循环,只使用标准Java库类:

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.

如您所见,我还为长度== 0的情况添加了合适的代码。

#4


28  

Some possible solutions.

一些可能的解决方

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

这将创建一个填充长度为“0”的字符串,然后使用charToFill(旧学校)替换“0”。

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.

这将创建一个List,其中包含使用charToFill的长度字符串,然后将List连接到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).

这将使用charToFill创建带有字符串的无限java8 Stream,将输出限制为length并使用String joiner(新学校)收集结果。

String s = Stream.generate(() -> String.valueOf(charToFill)).limit(length).collect(Collectors.joining());

#5


16  

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

#6


6  

Solution using Google Guava

使用Google Guava的解决方案

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

#7


5  

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?

哪里不对?

#8


5  

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

为了提高性能,如果您知道最大长度,则可以使用单个预定义的sting:

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

String template =“####################################”;

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

然后在知道长度后简单地执行子串。

#9


4  

using Dollar is simple:

使用Dollar很简单:

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

#10


4  

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

使用Google Guava的解决方案,因为我更喜欢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);
}

#11


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.

现在为我的工程解决方案。在许多(不是全部)情况下,您可以使用CharSequence而不是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);
  }
}

#12


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

另外需要注意的是:似乎所有创建新String实例的公共方法都必然包含您正在使用的任何缓冲区的副本,无论是char [],StringBuffer还是StringBuilder。从String javadoc(并在其他类的相应toString方法中重复):

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

因此,在“快速填充”数组之后,您最终会有一个可能很大的内存复制操作。可以避免此问题的唯一解决方案是来自@mlk的解决方案,如果您可以管理直接使用建议的CharSequence实现(可能是这种情况)。

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

PS:我会将此作为评论发布,但我还没有足够的声誉来做到这一点。

#13


1  

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

试试这个使用substring(int start,int end);方法

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

this will return abcde.

这将返回abcde。

#14


1  

Mi solution :

米解决方案:

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

The output :

输出 :

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

#15


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

#16


0  

You can use a while loop like this:

您可以像这样使用while循环:

String text = "Hello";
while (text.length() < 10) { text += "*"; }
System.out.println(text);

Will give you:

会给你:

Hello*****

Or get the same result with a custom method:

或者使用自定义方法获得相同的结果:

    public static String extendString(String text, String symbol, Integer len) {
        while (text.length() < len) { text += symbol; }
        return text;
    }

Then just call:

然后打电话:

extendString("Hello", "*", 10)

It may also be a good idea to set a length check to prevent infinite loop.

设置长度检查以防止无限循环也是一个好主意。

#17


0  

In Java 11, you have repeat:

在Java 11中,您重复:

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

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

(虽然在撰写本文时仍有待更改)