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


144

java中有没有一种方法可以用指定数量的指定字符创建字符串?就我而言,我需要创建一个包含10个空格的字符串。我当前的代码是:

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

有没有更好的方法来完成同一件事。特别是我想快速(在执行方面)。


1
如果您发现自己做了很多事情,只需编写一个函数:String characterRepeat(Char c,int Length){...},该函数可以对任何字符和任何长度进行处理。然后在需要时调用它。
奥斯汀·菲茨帕特里克

12
您想使用StringBuilder而不是StringBuffer

在开始时增加缓冲区的大小,很容易计算出一个方便内存管理中的东西!StringBuilder outputBuffer =新的StringBuilder(repeat * base.length());
维克多


如果您想附加一个空格,请append(' ')改用...这会减少计算量...
Erk

Answers:


36

for循环将由编译器优化。在像您这样的情况下,您无需自己担心优化。信任编译器。

顺便说一句,如果有一种方法可以创建一个包含n个空格字符的字符串,那么它的编码方式就和您刚才一样。


1
即使这不是最优化-这是在你的程序中创建多久-如果经常保存在一个静态变量或其他高速缓存
MMMMMM

btw Array.fill()只是遍历整个数组。/ me绝对需要更多积分才能对其他帖子发表评论:)
kalkin 2010年

@Mark Length是可变的,因此保存它似乎很愚蠢。我该怎么办,有一个static Dictionary<int, String>
C. Ross,2010年

1
存储您想要的最长字符串,然后使用类似以下的命令: " ".substring(0, 10);
mjaggard 2014年

169

可能是使用StringAPI 的最短代码,专门用于:

String space10 = new String(new char[10]).replace('\0', ' ');

System.out.println("[" + space10 + "]");
// prints "[          ]"

作为一种方法,无需直接实例化char

import java.nio.CharBuffer;

/**
 * Creates a string of spaces that is 'spaces' spaces long.
 *
 * @param spaces The number of spaces to add to the string.
 */
public String spaces( int spaces ) {
  return CharBuffer.allocate( spaces ).toString().replace( '\0', ' ' );
}

调用使用:

System.out.printf( "[%s]%n", spaces( 10 ) );

4
尽管我喜欢单行代码,但我认为FrustratedWithFormsDes的解决方案在执行时会更好,因为它避免了检查\ 0并简单地分配空间。
Bouncner 2013年

1
经过测试,它总是比循环快,始终一致地快50000-100000纳秒,这可能非常重要(0.1毫秒),尽管总时间仍然很高,但随着迭代次数的增加,循环的确会更快。当创建不同大小的空格字符串时,这适用。
kmecpp

扑通弥补相当不错的解决方案,我在我的答案用在这里stackoverflow.com/questions/852665/...
maytham-ɯɐɥʇʎɐɯ

66

嗯,现在我考虑一下,也许Arrays.fill

char[] charArray = new char[length];
Arrays.fill(charArray, ' ');
String str = new String(charArray);

当然,我假设该fill方法与您的代码执行相同的操作,因此它可能会执行相同的操作,但是至少这是更少的行。


2
检查源后,似乎这样做实际上是OP贴到底该怎么做:行806 docjar.com/html/api/java/util/Arrays.java.html
流行

2
@Torgamus阁下OP的问题是否已编辑?因为在我看到的版本中,他正在StringBuffer.append()上循环,而Frustrated的版本正在执行填充(当然,循环会执行对数组的char分配)。完全不一样。
CPerkins,2010年

@CPerkins,很公平,我不清楚。我的观点是,他们两个都在for循环中逐个字符地插入。
流行

1
@托加莫斯勋爵-同意这一点。可惜jvm不能做一个内存集。我们为宽字符支付的价格。
CPerkins,2010年

2
@Pops值得注意的是,如果在Arrays.fill()代码(标准和外部)库代码中一致地使用该函数来完成此工作,则它很适合用于Hotspot编译,并且更有可能找到您的CPU缓存。将来的JVM可能会将其分配为内部函数。自己
动手做会使

65

我强烈建议不要手动编写循环。您将在编程生涯中一遍又一遍地做。读取您的代码(包括您在内)的人们总是必须花时间,即使只是几秒钟,也要消化循环的含义。

而是重用可用的库之一,该库提供StringUtils.repeatApache Commons Lang类似的代码:

StringUtils.repeat(' ', length);

这样,您也不必担心性能,因此, StringBuilder,,编译器优化等的都被隐藏了。如果该函数的运行速度很慢,则可能是该库的错误。

使用Java 11,它变得更加容易:

" ".repeat(length);

5
另一方面,如果项目中尚未使用StringUtils,则为这样一个简单的任务添加另一个依赖关系可能就太过分了。
Erich Kitzmueller

1
如果结果很慢,您还可以提交自己的功能修复程序。


13

如果只需要空格,那么如何:

String spaces = (n==0)?"":String.format("%"+n+"s", "");

这将导致abs(n)空格;


6
那速度如何呢?我的印象格式比较慢。它必须先解析字符串,然后才能创建它。
C. Ross

11

Java 11开始

" ".repeat(10);

Java 8开始

generate(() -> " ").limit(10).collect(joining());

哪里:

import static java.util.stream.Collectors.joining;
import static java.util.stream.Stream.generate;

9

从Java 11开始,您可以简单地使用它String.repeat(count)来解决您的问题。

返回一个字符串,其值是该字符串的重复count次数。

如果此字符串为空或count为零,则返回空字符串。

因此,除了循环之外,您的代码将如下所示:

" ".repeat(length);

8

我认为这是可能的更少代码,它使用Guava Joiner类:

Joiner .on(“”)。join(Collections.nCopies(10,“”));


最短的代码行,但是为该简单任务添加一个大型库没有任何意义。我可以使用一个方法自己创建一个较小的JAR,该方法pubic String n(int n) { ... }甚至允许“更少”的代码:n(10),但是,这毫无意义。
isapir'1

@isapir对于已经使用番石榴的人来说,这是一个很好的答案
nasch

1
@nasch Guava不是问题的一部分。但是无论如何,在2018年,当您可以使用Java 8中添加的String.join()时,实际上没有理由使用Guava的Joiner。请参阅stackoverflow.com/a/43011939/968244
isapir

@isapir不,番石榴是一个答案。StackOverflow上的答案比问这个问题的人有更广泛的受众,因此,如果某些答案不是问这个人的最佳选择,那就很好。关于String.join()的评论很不错,尽管我不确定它是否适用于所有版本的Android(这是Java的主要用法)。
nasch

7

您可以使用标准String.format函数生成N个空格。例如:

String.format("%5c", ' ');

用5个空格组成一个字符串。

要么

int count = 15;
String fifteenSpacebars = String.format("%" + count + "c", ' ');

制作一个由15个空格键组成的字符串。

如果要重复另一个符号,则必须用所需的符号替换空格:

int count = 7;
char mySymbol = '#';
System.out.println(String.format("%" + count + "c", ' ').replaceAll("\\ ", "\\" + mySymbol));

输出:

#######

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

我针对另外两种方法测试了该算法:

  • 常规for循环String.concat()用于连接字符串
  • 常规for循环使用 StringBuilder

测试代码(使用for循环进行连接,并String.concat()变大时变慢n,因此在第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循环具有足够的速度

4
这是一个有趣的实现。不幸的是,与您的结论相反,对于大n而言,效率非常低。我怀疑这是由于每次连接字符串时都会进行许多内存分配。尝试将其写为采用StringBuilder而不是String的递归方法的包装。我敢打赌,您会发现结果会好得多。
Klitos Kyriacou,2015年

3
在对此类基准进行微基准测试时,您需要采取许多预防措施,我认为您没有采取任何预防措施!围绕此代码的主要性能问题很容易是它是否是Hotspot编译的,它会创建多少垃圾等等。我敢打赌,所有这些if语句都会弄乱CPU的分支预测。确实应该使用JMH(openjdk.java.net/projects/code-tools/jmh)重做,否则就没有意义了。
SusanW

请注意,此实现的复杂度为O(n * log n),而StringBuilder为O(n):)
Leo 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(使用流)

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

Java 8(使用nCopies)

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

1
Collectors.joining(EMPTY_STRING)等效于Collectors.joining()
PPartisan

2

RandomStringUtils可以根据给定的输入大小创建字符串。不能评论速度,但其一线。

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

创建一个输出

\ t \ t \ t \ t \ t

如果您不想在代码中看到\ 0,则更可取。


2

使用StringUtils:StringUtils.repeat('',10)


1

在大多数情况下,您只需要一定长度的字符串即可,例如100个空格。您可以准备一个字符串数组,其中索引号等于空格字符串的大小,并在所需长度在限制范围内的情况下查找该字符串,或者在边界之外按需创建。



0

只需将您的StringBuffer替换为StringBuilder。很难击败。

如果长度很大,则可以实现一些更有效(但更笨拙)的自动附加,在每次迭代中复制长度:

 public static String dummyString(char c, int len) {
  if( len < 1 ) return "";
  StringBuilder sb = new StringBuilder(len).append(c);
  int remnant = len - sb.length();
  while(remnant  > 0) {
   if( remnant  >= sb.length() ) sb.append(sb);
   else sb.append(sb.subSequence(0, remnant));
   remnant  = len - sb.length();
  }
  return sb.toString();
 }

另外,您可以尝试使用此方法Arrays.fill()FrustratedWithFormsDesigner的答案)。


您可以为多个变量指定多个字符吗?
罗斯

0

您可以替换StringBufferStringBuilder(后者不同步,在单线程应用中可能更快)

而且您可以创建StringBuilder一次实例,而不必在每次需要时都创建它。

像这样:

class BuildString {
     private final StringBuilder builder = new StringBuilder();
     public String stringOf( char c , int times ) {

         for( int i = 0 ; i < times ; i++  ) {
             builder.append( c );
         }
         String result = builder.toString();
         builder.delete( 0 , builder.length() -1 );
         return result;
      }

  }

并像这样使用它:

 BuildString createA = new BuildString();
 String empty = createA.stringOf( ' ', 10 );

如果您将其保留createA为实例变量,则可以节省创建实例的时间。

这不是线程安全的,如果您有多个线程,则每个线程应具有自己的副本。


0

为了获得良好的性能,请结合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个字符的长度。


0

有这样的方法。这会在给定的末尾附加所需的空格,String以使给定String的长度达到特定长度。

public static String fillSpaces (String str) {

    // the spaces string should contain spaces exceeding the max needed
    String spaces = "                                                   ";
    return str + spaces.substring(str.length());
}

0

希望String为固定大小,以便填充或截断以制表数据...

class Playground {
    private static String fixStrSize(String s, int n) {
        return String.format("%-" + n + "s", String.format("%." + n +"s", s));
    }

    public static void main(String[ ] args) {
        System.out.println("|"+fixStrSize("Hell",8)+"|");
        System.out.println("|"+fixStrSize("Hells Bells Java Smells",8)+"|");
    }
}

|Hell    |
|Hells Be|

这里的参考很好


0

这为我解决了,而无需使用Java 8中的任何外部库

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

输出是

testtesttest

0

整数c = 10; 字符串空间= String.format(“%” + c +“ c”,''; 这将解决您的问题。


-1

也可以使用下面的简单方法

public static String padString(String str, int leng,char chr) {
        for (int i = str.length(); i <= leng; i++)
            str += chr;
        return str;
    }

这实际上要慢一些。
SLaks

如果要处理的字符串很大,则可以使用StringBuffer代替字符串连接。这将在很大程度上影响速度
耶谢巴尔Singla

-2

这个怎么样?

public String fillSpaces(int len) {
    /* the spaces string should contain spaces exceeding the max needed */  
    String spaces = "                                                   ";
    return spaces.substring(0,len);
}

编辑:我编写了一个简单的代码来测试概念,并在这里找到了。

方法1:在循环中添加单个空格:

  public String execLoopSingleSpace(int len){
    StringBuilder sb = new StringBuilder();

    for(int i=0; i < len; i++) {
        sb.append(' ');
    }

    return sb.toString();
  }

方法2:附加100个空格并循环,然后添加子字符串:

  public String execLoopHundredSpaces(int len){
    StringBuilder sb = new StringBuilder("          ")
            .append("          ").append("          ").append("          ")
            .append("          ").append("          ").append("          ")
            .append("          ").append("          ").append("          ");

    for (int i=0; i < len/100 ; i++) {
        sb.append("          ")
            .append("          ").append("          ").append("          ")
            .append("          ").append("          ").append("          ")
            .append("          ").append("          ").append("          ");
    }

    return sb.toString().substring(0,len);
  }

我得到的结果是创建12,345,678个空格:

C:\docs\Projects> java FillSpace 12345678
method 1: append single spaces for 12345678 times. Time taken is **234ms**. Length of String is 12345678
method 2: append 100 spaces for 123456 times. Time taken is **141ms**. Length of String is 12345678
Process java exited with code 0

对于10,000,000个空格:

C:\docs\Projects> java FillSpace 10000000
method 1: append single spaces for 10000000 times. Time taken is **157ms**. Length of String is 10000000
method 2: append 100 spaces for 100000 times. Time taken is **109ms**. Length of String is 10000000
Process java exited with code 0

将直接分配与迭代结合在一起通常会花费更少的时间,而在创建巨大空间时平均要少60ms。对于较小的尺寸,两个结果都可以忽略不计。

但请继续发表评论:-)


3
@ @aznilamir:嗯,您要如何处理1万个空格?
Jayan 2012年

这个想法是结合循环和直接分配100个空间。以下是代码段:
aznilamir

为什么要使用多个追加来添加100个字符?为什么不追加一个100个字符?
nycynik '16

-3

我不知道您要问的内置方法。但是,对于较小的固定长度(如10),您的方法应该足够快。


如果只有它像10小固定长度
C.罗斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.