Простой способ повторить строку в Java - PullRequest
509 голосов
/ 05 августа 2009

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

String str = "abc";
String repeated = str.repeat(3);

repeated.equals("abcabcabc");

Относится к:

повтор строки javascript Создать строку NSSt, повторяя другую строку заданное количество раз

Отредактировано

Я стараюсь избегать циклов, когда они не являются полностью необходимыми, потому что:

  1. Они добавляют к числу строк кода, даже если они спрятаны в другой функции.

  2. Кто-то, читающий мой код, должен выяснить, что я делаю в этом цикле for. Даже если он закомментирован и имеет значимые имена переменных, они все равно должны убедиться, что он не делает ничего «умного».

  3. Программисты любят помещать умные вещи в циклы, даже если я пишу это «делай только то, что задумано», что не исключает появления кого-то и добавления некоторого дополнительного умного «исправления».

  4. Очень часто их легко ошибиться. Для циклов, включающих индексы, склонны генерировать по одной ошибке.

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

  6. Для циклов увеличьте количество мест, которые должен искать охотник за насекомыми.

Ответы [ 28 ]

830 голосов
/ 05 февраля 2011

Вот самая короткая версия (требуется Java 1.5+):

repeated = new String(new char[n]).replace("\0", s);

Где n - количество повторений строки, а s - повторяющаяся строка.

Не требуется импорт или библиотеки.

296 голосов
/ 05 августа 2009

Commons Lang StringUtils.repeat ()

Использование:

String str = "abc";
String repeated = StringUtils.repeat(str, 3);

repeated.equals("abcabcabc");
259 голосов
/ 28 июля 2011

Если вы используете Java <= 7 </strong>, это так просто:

// create a string made up of n copies of string s
String.format("%0" + n + "d", 0).replace("0", s);

В Java 8 и выше есть простой способ:

// create a string made up of n copies of string s
String.join("", Collections.nCopies(n, s));

Java 11 добавил новый метод repeat​(int count) специально для этого ( ссылка )

int n = 3;
"abc".repeat(n);
133 голосов
/ 02 марта 2018

Начиная с Java 11, есть метод String::repeat, который делает именно то, о чем вы просили:

String str = "abc";
String repeated = str.repeat(3);
repeated.equals("abcabcabc");

Его Javadoc говорит:

/**
 * Returns a string whose value is the concatenation of this
 * string repeated {@code count} times.
 * <p>
 * If this string is empty or count is zero then the empty
 * string is returned.
 *
 * @param count number of times to repeat
 *
 * @return A string composed of this string repeated
 * {@code count} times or the empty string if this
 * string is empty or count is zero
 *
 * @throws IllegalArgumentException if the {@code count} is
 * negative.
 *
 * @since 11
 */ 
131 голосов
/ 25 июля 2014

Java 8 String.join обеспечивает удобный способ сделать это в сочетании с Collections.nCopies:

// say hello 100 times
System.out.println(String.join("", Collections.nCopies(100, "hello")));
98 голосов
/ 22 августа 2009

Вот способ сделать это, используя только стандартные функции String и без явных циклов:

// create a string made up of  n  copies of  s
repeated = String.format(String.format("%%%ds", n), " ").replace(" ",s);
84 голосов
/ 21 мая 2012

Если вы похожи на меня и хотите использовать Google Guava, а не Apache Commons. Вы можете использовать метод repeat в классе Guava Strings.

Strings.repeat("-", 60);
49 голосов
/ 29 декабря 2014

С вы также можете использовать Stream.generate.

import static java.util.stream.Collectors.joining;
...
String repeated = Stream.generate(() -> "abc").limit(3).collect(joining()); //"abcabcabc"

и при необходимости вы можете обернуть его простым служебным методом:

public static String repeat(String str, int times) {
   return Stream.generate(() -> str).limit(times).collect(joining());
}
32 голосов
/ 06 августа 2009

То есть вы хотите избежать петель?

Вот оно:

public static String repeat(String s, int times) {
    if (times <= 0) return "";
    else return s + repeat(s, times-1);
}

(конечно, я знаю, что это уродливо и неэффективно, но у него нет петель :-p)

Вы хотите, чтобы это было проще и красивее? используйте jython:

s * 3

Редактировать : давайте немного его оптимизируем: -D

public static String repeat(String s, int times) {
   if (times <= 0) return "";
   else if (times % 2 == 0) return repeat(s+s, times/2);
   else return s + repeat(s+s, times/2);
}

Edit2 : Я сделал быстрый и грязный тест для 4 основных альтернатив, но у меня нет времени запустить его несколько раз, чтобы получить средства и построить график времени для нескольких входов. .. Так вот код, если кто-то хочет попробовать это:

public class Repeat {
    public static void main(String[] args)  {
        int n = Integer.parseInt(args[0]);
        String s = args[1];
        int l = s.length();
        long start, end;

        start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            if(repeatLog2(s,i).length()!=i*l) throw new RuntimeException();
        }
        end = System.currentTimeMillis();
        System.out.println("RecLog2Concat: " + (end-start) + "ms");

        start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            if(repeatR(s,i).length()!=i*l) throw new RuntimeException();
        }               
        end = System.currentTimeMillis();
        System.out.println("RecLinConcat: " + (end-start) + "ms");

        start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            if(repeatIc(s,i).length()!=i*l) throw new RuntimeException();
        }
        end = System.currentTimeMillis();
        System.out.println("IterConcat: " + (end-start) + "ms");

        start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            if(repeatSb(s,i).length()!=i*l) throw new RuntimeException();
        }
        end = System.currentTimeMillis();
        System.out.println("IterStrB: " + (end-start) + "ms");
    }

    public static String repeatLog2(String s, int times) {
        if (times <= 0) {
            return "";
        }
        else if (times % 2 == 0) {
            return repeatLog2(s+s, times/2);
        }
        else {
           return s + repeatLog2(s+s, times/2);
        }
    }

    public static String repeatR(String s, int times) {
        if (times <= 0) {
            return "";
        }
        else {
            return s + repeatR(s, times-1);
        }
    }

    public static String repeatIc(String s, int times) {
        String tmp = "";
        for (int i = 0; i < times; i++) {
            tmp += s;
        }
        return tmp;
    }

    public static String repeatSb(String s, int n) {
        final StringBuilder sb = new StringBuilder();
        for(int i = 0; i < n; i++) {
            sb.append(s);
        }
        return sb.toString();
    }
}

Требуется 2 аргумента, первый - количество итераций (каждая функция выполняется с временем повтора arg от 1..n), а второй - строка для повторения.

Пока быстрая проверка времени выполнения с разными входами оставляет рейтингу что-то вроде этого (лучше к худшему):

  1. Итеративное добавление StringBuilder (1x).
  2. Вызовы log2 с рекурсивной конкатенацией (~ 3x).
  3. Линейные вызовы рекурсивной конкатенации (~ 30x).
  4. Итеративная конкатенация линейная (~ 45x).

Я бы никогда не догадался, что рекурсивная функция работает быстрее, чем цикл for: -o

Развлекайся (ction xD).

20 голосов
/ 05 августа 2009

Содержит меньше символов, чем ваш вопрос

public static String repeat(String s, int n) {
    if(s == null) {
        return null;
    }
    final StringBuilder sb = new StringBuilder(s.length() * n);
    for(int i = 0; i < n; i++) {
        sb.append(s);
    }
    return sb.toString();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...