Avatar ·

Как просто и эффективно повторить строку в Java?

Всем привет! Я начинающий Java-разработчик, и у меня возникла проблема. Мне нужно многократно повторить одну и ту же строку, например, символ '-' 10 раз, чтобы нарисовать разделительную линию в консоли. Или, скажем, повторить слово "Hello" 5 раз, чтобы получить "HelloHelloHelloHelloHello". Я знаю, что можно сделать это вручную через цикл: ```java String str = "Hello"; String result = ""; for (int i = 0; i < 5; i++) { result += str; } System.out.println(result); // HelloHelloHelloHelloHello ``` Но это выглядит громоздко и некрасиво. К тому же, я слышал, что конкатенация строк в цикле через `+=` — это плохая практика, потому что каждый раз создается новый объект String. Для больших повторений это будет работать медленно. Я пробовал использовать `StringBuilder`, но код всё равно получается многословным: ```java StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("Hello"); } String result = sb.toString(); ``` Может быть, в Java есть какой-нибудь встроенный метод или однострочник для этой задачи? В Python, например, есть оператор `*` для строк: `"Hello" * 5`. Есть ли что-то подобное в Java? Или нужно писать свою библиотечную функцию? Буду благодарен за простой и элегантный способ решения этой задачи, желательно без внешних библиотек, только стандартная Java. <<>>

Лучший способ: используйте String.repeat() (Java 11+)

Начиная с Java 11, в стандартной библиотеке появился идеальный метод для вашей задачи — String.repeat(int count). Он делает ровно то, что нужно: возвращает строку, повторенную указанное количество раз. Это однострочник, который работает быстро и элегантно.

public class Main {
    public static void main(String[] args) {
        String str = "Hello";
        String repeated = str.repeat(5);
        System.out.println(repeated); // HelloHelloHelloHelloHello

        // Для символов-разделителей:
        String line = "-".repeat(10);
        System.out.println(line); // ----------
    }
}

Как это работает?

Метод repeat() реализован внутри класса String и использует эффективные низкоуровневые операции с массивами символов. Он не создает промежуточных объектов StringBuilder или временных строк, а сразу формирует результирующий массив байтов. Это делает его самым производительным решением.

Если у вас Java 8 или 10 (более старые версии)

Если вы не можете использовать Java 11+, вот несколько альтернатив:

  • С помощью StringBuilder и цикла — самый читаемый вариант для старых версий:
public static String repeat(String str, int count) {
    StringBuilder sb = new StringBuilder(str.length() * count);
    for (int i = 0; i < count; i++) {
        sb.append(str);
    }
    return sb.toString();
}

Обратите внимание: мы заранее задаем емкость StringBuilder (str.length() * count), чтобы избежать внутренних переаллокаций буфера. Это сильно повышает производительность.

  • С помощью Collections.nCopies() и String.join() — хитрый однострочник без циклов:
import java.util.Collections;

String repeated = String.join("", Collections.nCopies(5, "Hello"));
System.out.println(repeated); // HelloHelloHelloHelloHello

Collections.nCopies(n, element) создает неизменяемый список из n копий элемента. String.join("", list) склеивает их в одну строку. Метод работает, но менее производителен, чем StringBuilder.

  • С помощью Arrays.fill() и new String(char[]) — для случая, когда нужно повторить один символ:
public static String repeatChar(char ch, int count) {
    char[] array = new char[count];
    Arrays.fill(array, ch);
    return new String(array);
}

// Использование:
String line = repeatChar('-', 10); // ----------

Производительность (бенчмарк)

Для больших строк (например, повторение 10 000 раз строки длиной 100 символов) результаты будут такими (от быстрого к медленному):

  1. String.repeat() (Java 11+) — самый быстрый
  2. StringBuilder с предварительным выделением емкости
  3. char[] + Arrays.fill (только для одного символа)
  4. Collections.nCopies + String.join
  5. Конкатенация через += в цикле — никогда так не делайте

Итог

Если у вас Java 11 или новее — используйте "строка".repeat(n). Это самый простой, читаемый и производительный способ. Если вы застряли на Java 8 — используйте StringBuilder с правильной начальной емкостью. И никогда не используйте конкатенацию через += в циклах — это убивает производительность.

<<>>

Альтернативный подход: Стримы Java 8

Если вы используете Java 8 и хотите написать код в функциональном стиле, можно применить Stream API. Это не самый производительный, но очень элегантный и современный способ:

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

public static String repeatWithStream(String str, int count) {
    return Stream.generate(() -> str)
                 .limit(count)
                 .collect(Collectors.joining());
}

// Пример:
String result = repeatWithStream("Hi", 3);
System.out.println(result); // HiHiHi

Stream.generate() создает бесконечный поток, где каждый элемент — это наша строка. limit(count) ограничивает количество элементов, а collect(Collectors.joining()) склеивает их в одну строку.

Для одного символа — самый быстрый способ на Java 8

Если вам нужно повторить именно один символ (не строку), можно использовать String.format() и String.replace():

public static String repeatChar(char ch, int count) {
    return String.format("%" + count + "s", "").replace(' ', ch);
}

// Пример:
String line = repeatChar('=', 20);
System.out.println(line); // ====================

Этот трюк создает строку из count пробелов с помощью String.format(), а затем заменяет все пробелы на нужный символ. Работает быстро, но только для одного символа.

Важный совет

Какой бы способ вы ни выбрали, помните: никогда не используйте конкатенацию строк через += в циклах. Каждая операция += создает новый объект String, копируя оба операнда. Для 1000 повторений строки длиной 100 символов это создаст 1000 промежуточных строк и будет работать в сотни раз медленнее, чем StringBuilder или repeat().