创建一个包含n个字符的字符串。

186

在Java中是否有一种方法可以创建一个具有特定数量特定字符的字符串? 在我的情况下,我需要创建一个包含十个空格的字符串。 我当前的代码是:

final StringBuffer outputBuffer = new StringBuffer(length);
for (int i = 0; i < length; i++){
   outputBuffer.append(" ");
}
return outputBuffer.toString();

有没有更好的方法实现同样的事情?特别是,我想要一个执行速度快的解决方案。


1
如果你发现自己经常这样做,那就写一个函数:String characterRepeat(Char c, int Length){ ... },它可以针对任何字符和任何长度执行你所做的操作。然后在需要时只需调用它即可。 - Austin Fitzpatrick
12
建议使用 StringBuilder 而不是 StringBuffer。 - user177800
在缓冲区的开头添加大小,容易计算并简化内存管理!StringBuilder outputBuffer = new StringBuilder(repeat * base.length()); - Victor
1
参见:https://dev59.com/U3M_5IYBdhLWcg3ww2Ob - Dave Jarvis
如果您想添加一个空格,请使用append(' '),这样可以减少一些计算量。 - Erk
Java 8:Stream和nCopies - https://dev59.com/5XE85IYBdhLWcg3wYSZk#51925748 - akhil_mittal
27个回答

6

我根据快速幂算法做出了贡献。

/**
 * Repeats the given {@link String} n times.
 * 
 * @param str
 *            the {@link String} to repeat.
 * @param n
 *            the repetition count.
 * @throws IllegalArgumentException
 *             when the given repetition count is smaller than zero.
 * @return the given {@link String} repeated n times.
 */
public static String repeat(String str, int n) {
    if (n < 0)
        throw new IllegalArgumentException(
                "the given repetition count is smaller than zero!");
    else if (n == 0)
        return "";
    else if (n == 1)
        return str;
    else if (n % 2 == 0) {
        String s = repeat(str, n / 2);
        return s.concat(s);
    } else
        return str.concat(repeat(str, n - 1));
}

我对该算法进行了两种其他方法的测试:
  • 使用String.concat()连接字符串的常规for循环
  • 使用StringBuilder的常规for循环
测试代码(对于大型n,使用for循环和String.concat()连接变得太慢,因此在第5次迭代后我将其删除)。
/**
 * Test the string concatenation operation.
 * 
 * @param args
 */
public static void main(String[] args) {
    long startTime;
    String str = " ";

    int n = 1;
    for (int j = 0; j < 9; ++j) {
        n *= 10;
        System.out.format("Performing test with n=%d\n", n);

        startTime = System.currentTimeMillis();
        StringUtil.repeat(str, n);
        System.out
                .format("\tStringUtil.repeat() concatenation performed in    %d milliseconds\n",
                        System.currentTimeMillis() - startTime);

        if (j <5) {
            startTime = System.currentTimeMillis();
            String string = "";
            for (int i = 0; i < n; ++i)
                string = string.concat(str);
            System.out
                    .format("\tString.concat() concatenation performed in        %d milliseconds\n",
                            System.currentTimeMillis() - startTime);
        } else
            System.out
                    .format("\tString.concat() concatenation performed in        x milliseconds\n");
        startTime = System.currentTimeMillis();
        StringBuilder b = new StringBuilder();
        for (int i = 0; i < n; ++i)
            b.append(str);
        b.toString();
        System.out
                .format("\tStringBuilder.append() concatenation performed in %d milliseconds\n",
                        System.currentTimeMillis() - startTime);
    }
}

结果:

Performing test with n=10
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        0 milliseconds
    StringBuilder.append() concatenation performed in 0 milliseconds
Performing test with n=100
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        1 milliseconds
    StringBuilder.append() concatenation performed in 0 milliseconds
Performing test with n=1000
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        1 milliseconds
    StringBuilder.append() concatenation performed in 1 milliseconds
Performing test with n=10000
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        43 milliseconds
    StringBuilder.append() concatenation performed in 5 milliseconds
Performing test with n=100000
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        1579 milliseconds
    StringBuilder.append() concatenation performed in 1 milliseconds
Performing test with n=1000000
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        x milliseconds
    StringBuilder.append() concatenation performed in 10 milliseconds
Performing test with n=10000000
    StringUtil.repeat() concatenation performed in    7 milliseconds
    String.concat() concatenation performed in        x milliseconds
    StringBuilder.append() concatenation performed in 112 milliseconds
Performing test with n=100000000
    StringUtil.repeat() concatenation performed in    80 milliseconds
    String.concat() concatenation performed in        x milliseconds
    StringBuilder.append() concatenation performed in 1107 milliseconds
Performing test with n=1000000000
    StringUtil.repeat() concatenation performed in    1372 milliseconds
    String.concat() concatenation performed in        x milliseconds
    StringBuilder.append() concatenation performed in 12125 milliseconds

结论:

  • 对于大的n - 使用递归方法
  • 对于小的n - for循环具有足够的速度

5
这是一个有趣的实现。不幸的是,与你的结论相反,对于大的n来说它非常低效。我怀疑这是因为每次连接字符串时都会发生许多内存分配。尝试编写一个使用StringBuilder而不是String的递归方法的包装器。我敢打赌你会发现结果会好得多。 - Klitos Kyriacou
4
像这样微基准测试时需要注意很多预防措施,我认为您没有采取任何措施!这段代码主要的性能问题可能是它是否被Hotspot编译,它创建了多少垃圾等。我打赌所有这些“if”语句会破坏CPU的分支预测。最好使用JMH(http://openjdk.java.net/projects/code-tools/jmh/)重新编写,否则这有点毫无意义。 - SusanW
请注意,此实现的复杂度为O(n * log n),而StringBuilder为O(n) :) - Lev Leontev

4

考虑到我们有以下内容:

String c = "c"; // character to repeat, for empty it would be " ";
int n = 4; // number of times to repeat
String EMPTY_STRING = ""; // empty string (can be put in utility class)

Java 8 (Using Stream)

String resultOne = IntStream.range(0,n)
   .mapToObj(i->c).collect(Collectors.joining(EMPTY_STRING)); // cccc

Java 8 (Using nCopies)

String resultTwo = String.join(EMPTY_STRING, Collections.nCopies(n, c)); //cccc

1
Collectors.joining(EMPTY_STRING) is equivalent to Collectors.joining() - PPartisan

4
这个怎么样?
char[] bytes = new char[length];
Arrays.fill(bytes, ' ');
String str = new String(bytes);

3
这与现有答案相同。 - Krease

3

Use StringUtils: StringUtils.repeat(' ', 10)


3

2

int c = 10; String spaces = String.format("%" +c+ "c", ' '); 这个方法可以解决你的问题。


2

RandomStringUtils提供了从给定的输入大小创建字符串的功能。虽然我无法评论其速度,但它只需要一行代码。

RandomStringUtils.random(5,"\t");

创建一个输出

\t\t\t\t\t

如果您不想在代码中看到\0,则最好使用此方法。


2

在Java 8中,我成功地完成了这个任务,而没有使用任何外部库。

String sampleText = "test"
int n = 3;
String output = String.join("", Collections.nCopies(n, sampleText));
System.out.println(output);

输出结果为:

testtesttest

1

为了获得良好的性能,结合来自aznilamirFrustratedWithFormsDesigner的答案。

private static final String BLANKS = "                       ";
private static String getBlankLine( int length )
{
    if( length <= BLANKS.length() )
    {
        return BLANKS.substring( 0, length );
    }
    else
    {
        char[] array = new char[ length ];
        Arrays.fill( array, ' ' );
        return new String( array );
    }
}

根据您的需求调整BLANKS的大小。我的具体BLANKS字符串长度约为200个字符。


我喜欢你的想法,它可能不太漂亮,但非常聪明。 - Thales Valias

1
在大多数情况下,您只需要字符串长度达到一定限度,比如100个空格。您可以准备一个字符串数组,索引数字等于填充空格的字符串大小,并查找该字符串,如果所需长度在限制范围内,则使用它;如果超出了边界,则根据需要创建它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接