Создать строку с n символами

Есть ли способ в java для создания строки с указанным числом указанного символа? В моем случае мне нужно создать строку с 10 пробелами. Мой текущий код:

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

Есть ли лучший способ сделать то же самое. В частности, мне бы хотелось что-то быстрое (с точки зрения исполнения).

Ответ 1

Цикл for будет оптимизирован компилятором. В таких случаях, как ваш, вам не нужно заботиться о оптимизации самостоятельно. Доверяйте компилятору.:)

Edit: Btw, если есть способ создать строку с n пробелами, чем она закодирована так же, как вы только что сделали.

Ответ 2

Вероятно, самый короткий код с использованием API String, исключительно:

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

Ответ 3

Хм теперь, когда я думаю об этом, возможно Arrays.fill:

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

Конечно, я предполагаю, что метод fill делает то же самое, что и ваш код, поэтому он, вероятно, будет работать примерно одинаково, но по крайней мере это меньше строк.

Ответ 4

Я настоятельно рекомендую не писать цикл вручную. Вы будете делать это снова и снова в течение своей карьеры программиста. Люди, читающие ваш код - включая вас, - всегда должны тратить время, даже если это всего лишь несколько секунд, чтобы переварить смысл цикла.

Вместо этого повторно используйте одну из доступных библиотек, предоставляющих код, который делает то же StringUtils.repeat что StringUtils.repeat из Apache Commons Lang:

StringUtils.repeat(' ', length);

Таким образом, вам также не нужно беспокоиться о производительности, поэтому все подробности StringBuilder, оптимизации компилятора и т.д. Скрыты. Если функция будет работать медленно, это будет ошибкой библиотеки.

С Java 11 это становится еще проще:

" ".repeat(length);

Ответ 5

В Java 8 вы можете использовать String.join:

String.join("", Collections.nCopies(n, s));

Ответ 6

Если вы хотите только пробелы, то как насчет:

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

что приведет к абс (n) пространствам;

Ответ 7

Я думаю, что это меньше кода, возможно, он использует класс Guava Joiner:

Joiner.on( "" ). join (Collections.nCopies (10, ""));

Ответ 8

Мой вклад основан на алгоритме быстрого возведения в степень.

/**
 * 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() для объединения строки
  • Регулярно для цикла с использованием 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 - для цикла имеет достаточную скорость

Ответ 9

Вы можете использовать стандартную функцию 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));

Выход:

#######

Ответ 10

Учитывая, что мы имеем:

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

Ответ 11

Начиная с Java 11 вы можете просто использовать String.repeat(count) для решения вашей проблемы.

Возвращает строку, значением которой является конкатенация этой строки, повторяемая count раз.

Если эта строка пуста или count равен нулю, возвращается пустая строка.

Таким образом, вместо цикла ваш код будет выглядеть так:

" ".repeat(length);

Ответ 12

Как насчет этого?

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

Ответ 13

RandomStringUtils содержит условие для создания строки из заданного размера ввода. Не могу прокомментировать скорость, но это один лайнер.

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

создает выходной файл

\ т\т\т\т\т

предпочтительнее, если вы не хотите видеть \0 в своем коде.

Ответ 14

Использовать StringUtils: StringUtils.repeat('', 10)

Ответ 15

В большинстве случаев вам понадобятся только строки до длины сертификатов, скажем, 100 пробелов. Вы можете подготовить массив строк, где номер индекса равен размеру заполненной пробелом строки и искать строку, если требуемая длина находится в пределах или создавать ее по требованию, если она находится за пределами границы.

Ответ 16

Stream.generate(() -> ch).limit(n).collect(joining());

где:

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

  String ch = " ";
  int n = 10;

  Stream
      .generate(() -> ch)
      .limit(n)
      .collect(joining());

Ответ 17

Просто замените 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() aproach (ответ "Разочарованный запросWithFormsDesigner" ).

Ответ 18

Вы можете заменить StringBuffer на StringBuilder (последний не синхронизирован, может быть быстрее в приложении с одним потоком)

И вы можете создать экземпляр 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 как переменную экземпляра, вы можете сэкономить время на создание экземпляров.

Это не потокобезопасно, если у вас много потоков, каждый поток должен иметь свою собственную копию.

Ответ 19

Для хорошей производительности комбинируйте ответы aznilamir и FrustratedWithFormsDesigner

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 символов.

Ответ 20

У вас есть такой метод. Это добавляет требуемые пробелы в конце заданного 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());
}

Ответ 22

Можно также использовать простой метод, например, ниже

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

Ответ 23

как насчет этого?

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

EDIT: Я написал простой код, чтобы проверить концепцию, и вот что я нашел.

Способ 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

объединение прямого распределения и итерации всегда занимает меньше времени, в среднем на 60 мс при создании огромных пространств. Для меньших размеров оба результата незначительны.

Но, пожалуйста, продолжайте комментировать: -)

Ответ 24

Я не знаю встроенного метода для того, о чем вы спрашиваете. Однако для небольшой фиксированной длины, такой как 10, ваш метод должен быть достаточно быстрым.