807

I'm looking for a simple commons method or operator that allows me to repeat some string n times. I know I could write this using a for loop, but I wish to avoid for loops whenever necessary and a simple direct method should exist somewhere.

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

repeated.equals("abcabcabc");

Related to:

repeat string javascript Create NSString by repeating another string a given number of times

Edited

I try to avoid for loops when they are not completely necessary because:

  1. They add to the number of lines of code even if they are tucked away in another function.

  2. Someone reading my code has to figure out what I am doing in that for loop. Even if it is commented and has meaningful variables names, they still have to make sure it is not doing anything "clever".

  3. Programmers love to put clever things in for loops, even if I write it to "only do what it is intended to do", that does not preclude someone coming along and adding some additional clever "fix".

  4. They are very often easy to get wrong. For loops involving indexes tend to generate off by one bugs.

  5. For loops often reuse the same variables, increasing the chance of really hard to find scoping bugs.

  6. For loops increase the number of places a bug hunter has to look.

18
  • 48
    I understand that for loops can cause some real issues. But you shouldn't try to avoid for loops "at all costs" because if it costs you readability, maintainability, and speed, you're being counterproductive. This is one of those cases.
    – Imagist
    Commented Aug 5, 2009 at 21:39
  • 10
    "They add to the number of lines of code even if they are tucked away in another function"...wow, just wow. Big-O, not LoC Commented Aug 5, 2009 at 23:40
  • 9
    @imagist I'm avoiding for loops in situations where it costs me readability, and maintainability. I consider speed as the least important issue here (a non-issue in fact). I think for loops are overused and I am trying to learn to only use for loops when they are necessary and not as a default solution. Commented Aug 6, 2009 at 0:29
  • 4
    @Pyrolistical I'm not claiming performance or asymptotic benefits. Rather saying that by writing less code, and using library functions rather than reinventing the wheel I reduce the bug surface area(Lines of Code) while increasing readability. Both good things I'm sure you'll agree. Commented Aug 6, 2009 at 0:51
  • 4
    @e5;sorry for posting years later.I find this question so appropriate. If inserted in a method, arguments should be tested (times>=0), errors thrown etc.This adds robustness but also lines of code to read. Repeating a string is something unambiguous.Who reads the code knows exactly what a string.repeat does, even without a line of comment or javadoc.If we use a stable library, is reasonable to think that a so-simple function has no bugs,YET introduces some form of "robustness" check that we even need to worry about.If i could ask 10 improvements, this (kind of) things would be one.
    – AgostinoX
    Commented Sep 21, 2011 at 21:01

33 Answers 33

1018

Here is the shortest version (Java 1.5+ required):

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

Where n is the number of times you want to repeat the string and s is the string to repeat.

No imports or libraries needed.

13
  • 26
    I don't think it's obfuscated at all. Primitive types (char[], in this case) are instantiated with nulls, then a String is created from the char[], and the nulls are replaced() with the character you want in s
    – Amarok
    Commented Dec 13, 2012 at 18:10
  • 45
    While this is very clever (+1) I think it pretty much proves the point that for loops often make for clearer code Commented Jun 25, 2013 at 11:53
  • 96
    To those who complain about obfuscation, readability depends on literacy. This is perfectly clear in what it does and educational for those who may not see it right away. This is what you get with Java by the way.
    – dansalmo
    Commented Jan 9, 2014 at 16:15
  • 11
    This should really be marked as the answer. When your looking for a 'simple' solution, including external libraries should really be a last resort if a better alternative exists. And this is a very very good alternative. Commented Feb 20, 2014 at 10:07
  • 12
    @user686249: There are only replace(char oldChar, char newChar) and replace(CharSequence target, CharSequence replacement) so I don't see how that could work
    – user102008
    Commented Oct 6, 2014 at 18:18
592

If you are using Java <= 7, this is as "concise" as it gets:

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

In Java 8 and above there is a more readable way:

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

Finally, for Java 11 and above, there is a new repeat​(int count) method specifically for this purpose(link)

"abc".repeat(12);

Alternatively, if your project uses java libraries there are more options.

For Apache Commons:

StringUtils.repeat("abc", 12);

For Google Guava:

Strings.repeat("abc", 12);
6
  • 5
    The former causes an exception when n is zero.
    – user4910279
    Commented Jun 4, 2017 at 11:19
  • The java 8 example does not compile -> Type mismatch: cannot convert from List<Character> to CharSequence
    – Arigion
    Commented Aug 8, 2017 at 11:18
  • 8
    @Arigion s has to be String, not a Char
    – Caner
    Commented Aug 9, 2017 at 9:37
  • @Caner Thanks. My bad, I apologize. Apparently I was too tired yesterday. Sorry about downvoting. I'll remove the downvote as soon as I could (it's blocked until question is edited)
    – Arigion
    Commented Aug 10, 2017 at 6:04
  • 5
    For anyone curious, the new "blah".repeat(10) in >=Java 11 appears to be very efficient, allocating byte arrays directly much like StringBuilder. Probably the best way to repeat strings from here on out!
    – rococo
    Commented Aug 21, 2021 at 19:07
415
+100

String::repeat

". ".repeat(7)  // Seven period-with-space pairs: . . . . . . . 

New in Java 11 is the method String::repeat that does exactly what you asked for:

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

Its Javadoc says:

/**
 * 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
 */ 
3
  • 8
    @Nicolai source code for it, just in case someone cares hg.openjdk.java.net/jdk/jdk/file/fc16b5f193c7/src/java.base/…
    – Eugene
    Commented May 4, 2018 at 12:27
  • 13
    i have not even seen java 9 yet on the street (and will not for a long time..) - and 11 is apparently set to ship.. Commented Jul 21, 2018 at 20:38
  • 5
    Probably obvious, but you can call this method on a string literal too: "abc".repeat(3)
    – Boann
    Commented Jun 20, 2019 at 1:56
324

Commons Lang StringUtils.repeat()

Usage:

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

repeated.equals("abcabcabc");
14
  • 105
    using a one-method-dependency for the simplicity's sake in the long run can resulting in a jar-hell
    – dfa
    Commented Aug 5, 2009 at 20:03
  • 84
    Sure, except it's commons lang. I don't think I've ever seen a project over 5000 LOCS that didn't have commons lang. Commented Aug 5, 2009 at 20:05
  • 11
    Commons Lang is open source - download it and take a look. Of course it has a loop inside, but it's not quite as simple. A lot of effort went into profiling and optimizing that implementation.
    – ChssPly76
    Commented Aug 5, 2009 at 21:59
  • 31
    I don't avoid loops for performance reason (read my reasons in the question). When someone sees StringUtils.repeat, they know what I am doing. They don't have to worry that I attempted to write my own version of repeat and made a mistake. It is an atomic cognitive unit! Commented Aug 5, 2009 at 22:24
  • 7
    @Thorbjørn Ravn Andersen - it can get a LOT more interesting if things keep being taken out of context
    – ChssPly76
    Commented Aug 5, 2009 at 23:03
152

Java 8's String.join provides a tidy way to do this in conjunction with Collections.nCopies:

// say hello 100 times
System.out.println(String.join("", Collections.nCopies(100, "hello")));
4
  • 7
    thank you! For android TextUtils.join() can be used instead of String.join()
    – DewinDell
    Commented Dec 11, 2016 at 7:34
  • 2
    Thank you for this answer. It's seems to be the cleanest way without using any external API oder utility method! very good!! Commented Jan 6, 2017 at 10:07
  • 2
    The nice thing about this method is that with join you can provide a separator character which works out to be very handy if you are, say, building up a CSV list. With all the other methods you have a terminating joining character that needs to be stripped out in a separate operation.
    – DroidOS
    Commented Oct 15, 2018 at 8:10
  • this is a nice readable answer, but just for context (from a naive benchmark) it's 3-4x slower than just a for loop over a StringBuilder, i.e., StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100; i++) { sb.append("hello"); } return sb.toString();
    – ATOMP
    Commented Apr 24, 2022 at 20:10
104

Here's a way to do it using only standard String functions and no explicit loops:

// create a string made up of  n  copies of  s
repeated = String.format(String.format("%%%ds", n), " ").replace(" ",s);
6
  • 5
    Amazing :-) Although beware of n becoming zero…!
    – Yang Meyer
    Commented Jan 12, 2010 at 14:14
  • 1
    I think he meant replaceAll
    – fortran
    Commented Mar 11, 2010 at 10:15
  • 4
    @Vijay Dev & fortran: No, he meant replace(). In Java 1.5+, there is an overloaded version of replace() that takes two CharSequences (which include Strings): download.oracle.com/javase/1.5.0/docs/api/java/lang/…
    – user102008
    Commented Feb 4, 2011 at 22:32
  • 8
    @mzuba let's say n=3: it first formats a string to look something like %03d (%% is to escape the percentage sign), which is the formatting code to add 3 padding zeroes, then formats 0 with that, leading to 000, and finally replaces each 0 with the strings
    – fortran
    Commented Jul 15, 2013 at 14:49
  • 17
    You can make the solution less ugly and easier to understand: String.format("%0"+n+"d", 0).replace("0", s)
    – Artur
    Commented Nov 26, 2013 at 8:58
88

If you're like me and want to use Google Guava and not Apache Commons. You can use the repeat method in the Guava Strings class.

Strings.repeat("-", 60);
2
  • 4
    ... and get 3Mb of new dependencies. Commented May 25, 2018 at 20:57
  • 6
    @MonoThreaded I thought it would go without saying, but don't include guava just to do a string repeat. My answer was about if you're already using guava anyway then this is how you'd do it.
    – Jack
    Commented May 25, 2018 at 23:53
55

With , you can also use Stream.generate.

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

and you can wrap it in a simple utility method if needed:

public static String repeat(String str, int times) {
   return Stream.generate(() -> str).limit(times).collect(joining());
}
1
  • 7
    ... or return IntStream.range(0, times).mapToObj(i -> str).collect(joining()); which parallelizes better
    – Alexis C.
    Commented Oct 14, 2015 at 18:53
33

So you want to avoid loops?

Here you have it:

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

(of course I know this is ugly and inefficient, but it doesn't have loops :-p)

You want it simpler and prettier? use jython:

s * 3

Edit: let's optimize it a little bit :-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: I've done a quick and dirty benchmark for the 4 main alternatives, but I don't have time to run it several times to get the means and plot the times for several inputs... So here's the code if anybody wants to try it:

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

It takes 2 arguments, the first is the number of iterations (each function run with repeat times arg from 1..n) and the second is the string to repeat.

So far, a quick inspection of the times running with different inputs leaves the ranking something like this (better to worse):

  1. Iterative StringBuilder append (1x).
  2. Recursive concatenation log2 invocations (~3x).
  3. Recursive concatenation linear invocations (~30x).
  4. Iterative concatenation linear (~45x).

I wouldn't ever guessed that the recursive function was faster than the for loop :-o

Have fun(ctional xD).

8
  • 1
    +1 for recursion and obviously being a lisp hacker. I don't think this is so inefficient either, string concatenation isn't the warcrime it once was, because + really is just a stringBuilder UTH. See stackoverflow.com/questions/47605/java-string-concatenation and schneide.wordpress.com/2009/02/23/… . I wonder how much all those stack pushes and pops from the recursion cost, or if hotspot takes care of them. Really wish I had the free time to benchmark it. Someone else maybe? Commented Aug 6, 2009 at 1:31
  • @e5: fortran is right; this solution could be made more efficient. This implementation will unnecessarily create a new StringBuilder (and a new String) for each recursion. Still a nice solution though.
    – rob
    Commented Aug 6, 2009 at 3:02
  • 3
    @e5 I'd wish I were a Lisp hacker xD... If I were, I would have used a tail recursive function :-p
    – fortran
    Commented Aug 6, 2009 at 8:41
  • 1
    Microbenchmarks don't work well in Java. Trying to measure the speed of your implementations like that is not good.
    – ceklock
    Commented Dec 9, 2012 at 1:08
  • 1
    The reason why the repeatIc is slower than even the simple recursion is that compilers typically translate string concatenation to StringBuilder code which helps in complex scenarios but implies even more copying operations in the case of concatenating two strings. So, in this specific case, using tmp = tmp.concat(s); will be more efficient than tmp += s; This does not apply when you compile for Java 9 or newer with javac, as the code will use StringConcatFactory then, which will likely handle the two string case with the same performance as concat.
    – Holger
    Commented Jul 5 at 13:25
21

This contains less characters than your question

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();
}
8
  • 7
    It contains more characters than my answer StringUtils.repeat(str, n). Commented Aug 5, 2009 at 19:32
  • 9
    Unless you're already using Apache Commons, this answer is a lot less hassle - no downloading another library, including it in your classpath, making sure its license is compatible with yours, etc. Commented Aug 5, 2009 at 19:44
  • 7
    Please, never return null - in that case return an empty string, allowing you to always use the returned value unchecked. Otherwise, what I would recommend the poster to use. Commented Aug 5, 2009 at 22:52
  • 7
    Well, there are three ways to handle if s is null. 1. Pass the error (return null), 2. Hide the error (return ""), 3. Throw an NPE. Hiding the error and throwing an NPE are not cool, so I passed the error. Commented Aug 5, 2009 at 23:34
  • 2
    @EthanHeilman add the 2MB worth of commons-lang3.3.1-sources and you're not that good anymore ;) But if someone already has commons-lang, I support your answer.
    – TWiStErRob
    Commented Oct 3, 2013 at 20:02
9

based on fortran's answer, this is a recusive version that uses a StringBuilder:

public static void repeat(StringBuilder stringBuilder, String s, int times) {
    if (times > 0) {
        repeat(stringBuilder.append(s), s, times - 1);
    }
}

public static String repeat(String s, int times) {
    StringBuilder stringBuilder = new StringBuilder(s.length() * times);
    repeat(stringBuilder, s, times);
    return stringBuilder.toString();
}
1
  • 2
    looping rather than recursion would reduce the # of stack frames for large numbers of repeats. Commented Jun 29, 2014 at 2:56
7

using Dollar is simple as typing:

@Test
public void repeatString() {
    String string = "abc";
    assertThat($(string).repeat(3).toString(), is("abcabcabc"));
}

PS: repeat works also for array, List, Set, etc

2
  • 3
    is the assertThat() method really needed?
    – ceklock
    Commented Dec 16, 2012 at 23:35
  • Link in answer gives "404 | Repository not found".
    – Pang
    Commented Aug 24, 2023 at 1:18
7

I wanted a function to create a comma-delimited list of question marks for JDBC purposes, and found this post. So, I decided to take two variants and see which one performed better. After 1 million iterations, the garden-variety StringBuilder took 2 seconds (fun1), and the cryptic supposedly more optimal version (fun2) took 30 seconds. What's the point of being cryptic again?

private static String fun1(int size) {
    StringBuilder sb = new StringBuilder(size * 2);
    for (int i = 0; i < size; i++) {
        sb.append(",?");
    }
    return sb.substring(1);
}

private static String fun2(int size) {
    return new String(new char[size]).replaceAll("\0", ",?").substring(1);
}
1
  • 3
    I makes sense that the second one would take much longer. It is performing a string search and then modifying the string character by character. Commented Dec 6, 2012 at 16:14
7

OOP Solution

Nearly every answer proposes a static function as a solution, but thinking Object-Oriented (for reusability-purposes and clarity) I came up with a Solution via Delegation through the CharSequence-Interface (which also opens up usability on mutable CharSequence-Classes).

The following Class can be used either with or without Separator-String/CharSequence and each call to "toString()" builds the final repeated String. The Input/Separator are not only limited to String-Class, but can be every Class which implements CharSequence (e.g. StringBuilder, StringBuffer, etc)!

Source-Code:

/**
 * Helper-Class for Repeating Strings and other CharSequence-Implementations
 * @author Maciej Schuttkowski
 */
public class RepeatingCharSequence implements CharSequence {
    final int count;
    CharSequence internalCharSeq = "";
    CharSequence separator = "";
    /**
     * CONSTRUCTOR - RepeatingCharSequence
     * @param input CharSequence to repeat
     * @param count Repeat-Count
     */
    public RepeatingCharSequence(CharSequence input, int count) {
        if(count < 0)
            throw new IllegalArgumentException("Can not repeat String \""+input+"\" less than 0 times! count="+count);
        if(count > 0)
            internalCharSeq = input;
        this.count = count;
    }
    /**
     * CONSTRUCTOR - Strings.RepeatingCharSequence
     * @param input CharSequence to repeat
     * @param count Repeat-Count
     * @param separator Separator-Sequence to use
     */
    public RepeatingCharSequence(CharSequence input, int count, CharSequence separator) {
        this(input, count);
        this.separator = separator;
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        checkBounds(start);
        checkBounds(end);
        int subLen = end - start;
        if (subLen < 0) {
            throw new IndexOutOfBoundsException("Illegal subSequence-Length: "+subLen);
        }
        return (start == 0 && end == length()) ? this
                    : toString().substring(start, subLen);
    }
    @Override
    public int length() {
        //We return the total length of our CharSequences with the separator 1 time less than amount of repeats:
        return count < 1 ? 0
                : ( (internalCharSeq.length()*count) + (separator.length()*(count-1)));
    }
    @Override
    public char charAt(int index) {
        final int internalIndex = internalIndex(index);
        //Delegate to Separator-CharSequence or Input-CharSequence depending on internal index:
        if(internalIndex > internalCharSeq.length()-1) {
            return separator.charAt(internalIndex-internalCharSeq.length());
        }
        return internalCharSeq.charAt(internalIndex);
    }
    @Override
    public String toString() {
        return count < 1 ? ""
                : new StringBuilder(this).toString();
    }

    private void checkBounds(int index) {
        if(index < 0 || index >= length())
            throw new IndexOutOfBoundsException("Index out of Bounds: "+index);
    }
    private int internalIndex(int index) {
        // We need to add 1 Separator-Length to total length before dividing,
        // as we subtracted one Separator-Length in "length()"
        return index % ((length()+separator.length())/count);
    }
}

Usage-Example:

public static void main(String[] args) {
    //String input = "12345";
    //StringBuffer input = new StringBuffer("12345");
    StringBuilder input = new StringBuilder("123");
    //String separator = "<=>";
    StringBuilder separator = new StringBuilder("<=");//.append('>');
    int repeatCount = 2;

    CharSequence repSeq = new RepeatingCharSequence(input, repeatCount, separator);
    String repStr = repSeq.toString();

    System.out.println("Repeat="+repeatCount+"\tSeparator="+separator+"\tInput="+input+"\tLength="+input.length());
    System.out.println("CharSeq:\tLength="+repSeq.length()+"\tVal="+repSeq);
    System.out.println("String :\tLength="+repStr.length()+"\tVal="+repStr);

    //Here comes the Magic with a StringBuilder as Input, as you can append to the String-Builder
    //and at the same Time your Repeating-Sequence's toString()-Method returns the updated String :)
    input.append("ff");
    System.out.println(repSeq);
    //Same can be done with the Separator:
    separator.append("===").append('>');
    System.out.println(repSeq);
}

Example-Output:

Repeat=2    Separator=<=    Input=123   Length=3
CharSeq:    Length=8    Val=123<=123
String :    Length=8    Val=123<=123
123ff<=123ff
123ff<====>123ff
0
6

using only JRE classes (System.arraycopy) and trying to minimize the number of temp objects you can write something like:

public static String repeat(String toRepeat, int times) {
    if (toRepeat == null) {
        toRepeat = "";
    }

    if (times < 0) {
        times = 0;
    }

    final int length = toRepeat.length();
    final int total = length * times;
    final char[] src = toRepeat.toCharArray();
    char[] dst = new char[total];

    for (int i = 0; i < total; i += length) {
        System.arraycopy(src, 0, dst, i, length);
    }

    return String.copyValueOf(dst);
}

EDIT

and without loops you can try with:

public static String repeat2(String toRepeat, int times) {
    if (toRepeat == null) {
        toRepeat = "";
    }

    if (times < 0) {
        times = 0;
    }

    String[] copies = new String[times];
    Arrays.fill(copies, toRepeat);
    return Arrays.toString(copies).
              replace("[", "").
              replace("]", "").
              replaceAll(", ", "");
}

EDIT 2

using Collections is even shorter:

public static String repeat3(String toRepeat, int times) {
    return Collections.nCopies(times, toRepeat).
           toString().
           replace("[", "").
           replace("]", "").
           replaceAll(", ", "");
}

however I still like the first version.

8
  • 6
    -1: too clever by half. If your aim is to make you code readable or efficient, these "solutions" are not a good idea. 'repeat' could simply be rewritten using a StringBuilder (setting the initial capacity). And 'repeat2' / 'repeat3' are really inefficient, and depend on the unspecified syntax of the String produced by String[].toString().
    – Stephen C
    Commented Aug 5, 2009 at 23:14
  • @Thorb: absolutely, with this code you cannot use "metacharacter", [],
    – dfa
    Commented Aug 6, 2009 at 2:22
  • @Stephen: the question was edited to request explicitly no loops. A StringBuilder based answer was already provided so I avoided to post a duplicate
    – dfa
    Commented Aug 6, 2009 at 2:25
  • @Stephan: I cannot figure out the downvote. My edited answer is loop-free as requeted. There are no requests about efficiency. I think that this question is just an intellectual effort to produce a concatenation without a loop.
    – dfa
    Commented Aug 6, 2009 at 2:50
  • @Stephan: String produced via Collection.toString (and Arrays.toString) are clearly specified in AbstractCollection.toString: " The string representation consists of a list of the collection's elements in the order they are returned by its iterator, enclosed in square brackets ("[]"). Adjacent elements are separated by the characters ", " (comma and space)."
    – dfa
    Commented Aug 6, 2009 at 3:04
6

Not the shortest, but (i think) the fastest way is to use the StringBuilder:

 /**
   * Repeat a String as many times you need.
   *
   * @param i - Number of Repeating the String.
   * @param s - The String wich you want repeated.
   * @return The string n - times.
   */
  public static String repeate(int i, String s) {
    StringBuilder sb = new StringBuilder();
    for (int j = 0; j < i; j++)
      sb.append(s);
    return sb.toString();
  }
0
5

If speed is your concern, then you should use as less memory copying as possible. Thus it is required to work with arrays of chars.

public static String repeatString(String what, int howmany) {
    char[] pattern = what.toCharArray();
    char[] res = new char[howmany * pattern.length];
    int length = pattern.length;
    for (int i = 0; i < howmany; i++)
        System.arraycopy(pattern, 0, res, i * length, length);
    return new String(res);
}

To test speed, a similar optimal method using StirngBuilder is like this:

public static String repeatStringSB(String what, int howmany) {
    StringBuilder out = new StringBuilder(what.length() * howmany);
    for (int i = 0; i < howmany; i++)
        out.append(what);
    return out.toString();
}

and the code to test it:

public static void main(String... args) {
    String res;
    long time;

    for (int j = 0; j < 1000; j++) {
        res = repeatString("123", 100000);
        res = repeatStringSB("123", 100000);
    }

    time = System.nanoTime();
    res = repeatString("123", 1000000);
    time = System.nanoTime() - time;
    System.out.println("elapsed repeatString: " + time);

    time = System.nanoTime();
    res = repeatStringSB("123", 1000000);
    time = System.nanoTime() - time;
    System.out.println("elapsed repeatStringSB: " + time);

}

And here the run results from my system:

elapsed repeatString: 6006571
elapsed repeatStringSB: 9064937

Note that the test for loop is to kick in JIT and have optimal results.

0
5

a straightforward one-line solution:
requires Java 8

Collections.nCopies( 3, "abc" ).stream().collect( Collectors.joining() );
4

for the sake of readability and portability:

public String repeat(String str, int count){
    if(count <= 0) {return "";}
    return new String(new char[count]).replace("\0", str);
}
3

If you are worried about performance, just use a StringBuilder inside the loop and do a .toString() on exit of the Loop. Heck, write your own Util Class and reuse it. 5 Lines of code max.

0
3

Seeing a number of StringBuilder related answers, I believe it's also worth mentioning that there are new StringBuilder.repeat and StringBuffer.repeat methods added in Java 21 to simplify the appending of multiple copies of characters or strings:

System.out.println(new StringBuilder().repeat('A', 10)); // AAAAAAAAAA

System.out.println(new StringBuilder().repeat("A1", 2)); // A1A1
2

I really enjoy this question. There is a lot of knowledge and styles. So I can't leave it without show my rock and roll ;)

{
    String string = repeat("1234567890", 4);
    System.out.println(string);
    System.out.println("=======");
    repeatWithoutCopySample(string, 100000);
    System.out.println(string);// This take time, try it without printing
    System.out.println(string.length());
}

/**
 * The core of the task.
 */
@SuppressWarnings("AssignmentToMethodParameter")
public static char[] repeat(char[] sample, int times) {
    char[] r = new char[sample.length * times];
    while (--times > -1) {
        System.arraycopy(sample, 0, r, times * sample.length, sample.length);
    }
    return r;
}

/**
 * Java classic style.
 */
public static String repeat(String sample, int times) {
    return new String(repeat(sample.toCharArray(), times));
}

/**
 * Java extreme memory style.
 */
@SuppressWarnings("UseSpecificCatch")
public static void repeatWithoutCopySample(String sample, int times) {
    try {
        Field valueStringField = String.class.getDeclaredField("value");
        valueStringField.setAccessible(true);
        valueStringField.set(sample, repeat((char[]) valueStringField.get(sample), times));
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}

Do you like it?

1
  • 1
    In my more extreme test, I produce a 1,700,000,000 (1.7 gigas) string repeat length,, using -Xms4937m Commented Apr 3, 2013 at 1:18
2
public static String repeat(String str, int times) {
    int length = str.length();
    int size = length * times;
    char[] c = new char[size];
    for (int i = 0; i < size; i++) {
        c[i] = str.charAt(i % length);
    }
    return new String(c);
}
2

Simple loop

public static String repeat(String string, int times) {
    StringBuilder out = new StringBuilder();
    while (times-- > 0) {
        out.append(string);
    }
    return out.toString();
}
1
  • 2
    pass times to StringBuilder constructor.
    – Behrouz.M
    Commented Mar 19, 2015 at 17:30
2

Try this out:

public static char[] myABCs = {'a', 'b', 'c'};
public static int numInput;
static Scanner in = new Scanner(System.in);

public static void main(String[] args) {
    System.out.print("Enter Number of Times to repeat: ");
    numInput = in.nextInt();
    repeatArray(numInput);
}

public static int repeatArray(int y) {
    for (int a = 0; a < y; a++) {
        for (int b = 0; b < myABCs.length; b++) {
            System.out.print(myABCs[b]);                
        }
        System.out.print(" ");
    }
    return y;
}
0
2

Using recursion, you can do the following (using ternary operators, one line max):

public static final String repeat(String string, long number) {
    return number == 1 ? string : (number % 2 == 0 ? repeat(string + string, number / 2) : string + repeat(string + string, (number - 1) / 2));
}

I know, it's ugly and probably not efficient, but it's one line!

4
  • This is the approach I would take but why do more checks than is needed? return number > 0 ? string + repeat(string, number-1) : "";
    – Fering
    Commented Dec 7, 2018 at 13:50
  • Oh, seems niczm25 answered with it below
    – Fering
    Commented Dec 7, 2018 at 13:52
  • @Fering main reason so that this way is O(log N) average rather than O(N) always. Slightly more optimization than the other one, though still bad nevertheless. Commented Dec 7, 2018 at 18:49
  • and never call it with number being negative or zero
    – user85421
    Commented Jul 14 at 10:04
2

If you only know the length of the output string (and it may be not divisible by the length of the input string), then use this method:

static String repeat(String s, int length) {
    return s.length() >= length ? s.substring(0, length) : repeat(s + s, length);
}

Usage demo:

for (int i = 0; i < 50; i++)
    System.out.println(repeat("_/‾\\", i));

Don't use with empty s and length > 0, since it's impossible to get the desired result in this case.

1

Despite your desire not to use loops, I think you should use a loop.

String repeatString(String s, int repetitions)
{
    if(repetitions < 0) throw SomeException();

    else if(s == null) return null;

    StringBuilder stringBuilder = new StringBuilder(s.length() * repetitions);

    for(int i = 0; i < repetitions; i++)
        stringBuilder.append(s);

    return stringBuilder.toString();
}

Your reasons for not using a for loop are not good ones. In response to your criticisms:

  1. Whatever solution you use will almost certainly be longer than this. Using a pre-built function only tucks it under more covers.
  2. Someone reading your code will have to figure out what you're doing in that non-for-loop. Given that a for-loop is the idiomatic way to do this, it would be much easier to figure out if you did it with a for loop.
  3. Yes someone might add something clever, but by avoiding a for loop you are doing something clever. That's like shooting yourself in the foot intentionally to avoid shooting yourself in the foot by accident.
  4. Off-by-one errors are also mind-numbingly easy to catch with a single test. Given that you should be testing your code, an off-by-one error should be easy to fix and catch. And it's worth noting: the code above does not contain an off-by-one error. For loops are equally easy to get right.
  5. So don't reuse variables. That's not the for-loop's fault.
  6. Again, so does whatever solution you use. And as I noted before; a bug hunter will probably be expecting you to do this with a for loop, so they'll have an easier time finding it if you use a for loop.
9
  • 3
    -1. Here's two exercises for you: a) run your code with repetitions = -5. b) download Commons Lang and run repeatString('a', 1000) a million times in a loop; do the same with your code; compare the times. For extra credit do the same with repeatString('ab', 1000).
    – ChssPly76
    Commented Aug 5, 2009 at 22:04
  • 2
    Are you arguing that your code is more readable then StringUtils.repeat("ab",1000)? Because that was my answer that you've downvoted. It also performs better and has no bugs.
    – ChssPly76
    Commented Aug 5, 2009 at 22:19
  • 2
    Read the 2nd sentence in the question you're quoting. "I try to avoid for loops at all costs because" was added to the question as a clarification in response to Andrew Hare's answer after my reply - not that it matters because if the position you're taking is "answer is bad if loop is used anywhere" there are no answers to the OP question. Even dfa's solutions - inventive as they are - use for loops inside. "jar hell" was replied to above; commons lang is used in every decent-sized application anyway and thus doesn't add a new dependency.
    – ChssPly76
    Commented Aug 5, 2009 at 23:01
  • 2
    @ChssPly76 at this point I'm pretty sure imagist is trolling. I really have a hard time seeing how anyone could read what I wrote and seriously think the responses typed above. Commented Aug 6, 2009 at 0:37
  • 1
    @ChssPly76 my answers don't have any loops at all :-p
    – fortran
    Commented Aug 6, 2009 at 13:54
0

here is the latest Stringutils.java StringUtils.java

    public static String repeat(String str, int repeat) {
    // Performance tuned for 2.0 (JDK1.4)

    if (str == null) {
        return null;
    }
    if (repeat <= 0) {
        return EMPTY;
    }
    int inputLength = str.length();
    if (repeat == 1 || inputLength == 0) {
        return str;
    }
    if (inputLength == 1 && repeat <= PAD_LIMIT) {
        return repeat(str.charAt(0), repeat);
    }

    int outputLength = inputLength * repeat;
    switch (inputLength) {
        case 1 :
            return repeat(str.charAt(0), repeat);
        case 2 :
            char ch0 = str.charAt(0);
            char ch1 = str.charAt(1);
            char[] output2 = new char[outputLength];
            for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
                output2[i] = ch0;
                output2[i + 1] = ch1;
            }
            return new String(output2);
        default :
            StringBuilder buf = new StringBuilder(outputLength);
            for (int i = 0; i < repeat; i++) {
                buf.append(str);
            }
            return buf.toString();
    }
    }

it doesn't even need to be this big, can be made into this, and can be copied and pasted into a utility class in your project.

    public static String repeat(String str, int num) {
    int len = num * str.length();
    StringBuilder sb = new StringBuilder(len);
    for (int i = 0; i < times; i++) {
        sb.append(str);
    }
    return sb.toString();
    }

So e5, I think the best way to do this would be to simply use the above mentioned code,or any of the answers here. but commons lang is just too big if it's a small project

1
  • I don't think there is much else you can do... excet maybe an AOT!! Commented Aug 11, 2011 at 5:01
0

I created a recursive method that do the same thing you want.. feel free to use this...

public String repeat(String str, int count) {
    return count > 0 ?  repeat(str, count -1) + str: "";
}

i have the same answer on Can I multiply strings in java to repeat sequences?

2
  • Needless string reallocation, and recursion overhead... bad, bad, not good.
    – Alexander
    Commented Nov 30, 2016 at 23:56
  • 1
    This will be slow. Not recommended! Use StringBuilder instead. Commented Oct 30, 2017 at 7:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.