重复字符串的简单方法

Posted

技术标签:

【中文标题】重复字符串的简单方法【英文标题】:Simple way to repeat a string 【发布时间】:2010-11-17 03:17:01 【问题描述】:

我正在寻找一种简单的公共方法或运算符,它允许我重复某些字符串 n 次。我知道我可以使用 for 循环来编写它,但我希望在必要时避免使用 for 循环,并且应该在某个地方存在一个简单的直接方法。

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

repeated.equals("abcabcabc");

相关:

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

已编辑

当 for 循环不是完全必要时,我会尽量避免它们,因为:

    即使它们隐藏在另一个函数中,它们也会增加代码行数。

    阅读我的代码的人必须弄清楚我在那个 for 循环中做了什么。即使它被注释并且具有有意义的变量名称,他们仍然必须确保它没有做任何“聪明”的事情。

    程序员喜欢将聪明的东西放入 for 循环中,即使我将其写为“只做它打算做的事情”,但这并不妨碍有人加入并添加一些额外的聪明“修复”。

    它们通常很容易出错。涉及索引的 for 循环往往会产生一个错误。

    For 循环经常重复使用相同的变量,增加了很难找到范围界定错误的机会。

    For 循环增加了 bug 搜寻者必须查看的地方的数量。

【问题讨论】:

我知道 for 循环可能会导致一些实际问题。但是您不应该“不惜一切代价”避免 for 循环,因为如果它损害了您的可读性、可维护性和速度,那么您将适得其反。这是其中一种情况。 “即使它们隐藏在另一个函数中,它们也会增加代码行数”......哇,哇。 Big-O,不是 LoC @imagist 我会避免在降低可读性和可维护性的情况下使用 for 循环。我认为速度是这里最不重要的问题(实际上不是问题)。我认为 for 循环被过度使用了,我正在努力学习只在必要时使用 for 循环,而不是作为默认解决方案。 @Pyrolistical 我没有声称性能或渐近收益。而是说通过编写更少的代码,使用库函数而不是重新发明***,我减少了错误表面积(代码行),同时提高了可读性。这两件好事我相信你会同意的。 @e5;很抱歉多年后才发帖。我觉得这个问题很合适。如果插入方法中,则应测试参数(次数> = 0),抛出错误等。这增加了健壮性,但也增加了要阅读的代码行。重复一个字符串是明确的。读过代码的人都知道 string.repeat 做了什么,即使没有一行注释或 javadoc。如果我们使用一个稳定的库,那么认为一个如此简单的函数没有错误是合理的, YET 引入了某种形式的“稳健性”检查,我们甚至需要担心。如果我可以提出 10 项改进,这(某种)事情就是其中之一。 【参考方案1】:

这是最短的版本(需要 Java 1.5+):

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

其中n 是您要重复字符串的次数,s 是要重复的字符串。

不需要导入或库。

【讨论】:

我认为它根本没有被混淆。原始类型(在本例中为char[])用空值实例化,然后从char[] 创建一个String,空值是replaced()s 中所需的字符 虽然这非常聪明(+1),但我认为它几乎证明了 for 循环通常会使代码更清晰的观点 对于那些抱怨混淆的人来说,可读性取决于读写能力。对于那些可能无法立即看到它的人来说,它的作用和教育意义非常清楚。顺便说一句,这就是你使用 Java 所得到的。 这确实应该被标记为答案。当您寻找“简单”解决方案时,如果存在更好的替代方案,包括外部库确实应该是最后的手段。这是一个非常非常好的选择。 为了更好的性能应该使用...replace('\0', str)而不是字符串版本。【参考方案2】:

如果您使用的是 Java ,这将尽可能“简洁”:

// 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) 方法(link)

"abc".repeat(12);

或者,如果您的项目使用 java 库,还有更多选择。

对于Apache Commons

StringUtils.repeat("abc", 12);

对于Google Guava

Strings.repeat("abc", 12);

【讨论】:

前者在n为零时引发异常。 java 8 示例无法编译 -> 类型不匹配:无法从 List 转换为 CharSequence @Arigion s 必须是字符串,而不是 Char @Caner 谢谢。我的错,我道歉。看来我昨天太累了。很抱歉投反对票。我会尽快删除反对票(在编辑问题之前它会被阻止) 对于任何好奇的人来说,>=Java 11 中的新"blah".repeat(10) 似乎非常高效,直接分配字节数组很像StringBuilder。可能是从现在开始重复字符串的最佳方式!【参考方案3】:

String::repeat

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

New in 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
 */ 

【讨论】:

@Nicolai 源代码,以防万一有人关心hg.openjdk.java.net/jdk/jdk/file/fc16b5f193c7/src/java.base/… 我什至还没有在街上看到过 java 9 (并且不会在 很长时间 时间......) - 和 11 显然已准备好发货.. 可能很明显,但您也可以在字符串文字上调用此方法:"abc".repeat(3) 很棒的内置方法!【参考方案4】:

Commons Lang StringUtils.repeat()

用法:

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

repeated.equals("abcabcabc");

【讨论】:

从长远来看,为了简单起见而使用单一方法依赖可能会导致 jar-hell 当然,但它是 commons lang。我认为我从未见过一个超过 5000 LOCS 的项目没有公共语言。 Commons Lang 是开源的 - 下载并查看。当然它里面有一个循环,但它并不那么简单。在分析和优化该实现方面付出了很多努力。 出于性能原因,我不会避免循环(请阅读问题中的原因)。当有人看到 StringUtils.repeat 时,他们就知道我在做什么。他们不必担心我尝试编写自己的重复版本并犯了错误。它是一个原子认知单元! @Thorbjørn Ravn Andersen - 如果事情不断脱离上下文,它会变得更有趣【参考方案5】:

Java 8 的 String.join 提供了一种与 Collections.nCopies 结合使用的简洁方式:

// say hello 100 times
System.out.println(String.join("", Collections.nCopies(100, "hello")));

【讨论】:

谢谢!对于 android 可以使用 TextUtils.join() 代替 String.join() 感谢您的回答。这似乎是不使用任何外部 API oder 实用程序方法的最干净的方法!很好!! 这个方法的好处是,如果你想建立一个 CSV 列表,你可以通过 join 提供一个分隔符,这非常方便。对于所有其他方法,您有一个终止连接字符,需要在单独的操作中删除。【参考方案6】:

这是一种只使用标准字符串函数而不使用显式循环的方法:

// create a string made up of  n  copies of  s
repeated = String.format(String.format("%%%ds", n), " ").replace(" ",s);

【讨论】:

太棒了 :-) 虽然要小心 n 变为零……! 我认为他的意思是replaceAll @Vijay Dev & fortran:不,他的意思是replace()。在 Java 1.5+ 中,有一个重载版本的 replace() 需要两个 CharSequences(包括 Strings):download.oracle.com/javase/1.5.0/docs/api/java/lang/… @mzuba 假设n=3:它首先将字符串格式化为类似于%03d%% 用于转义百分号),这是添加3个填充零的格式化代码, 然后用它格式化0,导致000,最后用字符串替换每个0 你可以让解决方案不那么难看,更容易理解:String.format("%0"+n+"d", 0).replace("0", s)【参考方案7】:

如果您像我一样想使用 Google Guava 而不是 Apache Commons。您可以在 Guava Strings 类中使用repeat 方法。

Strings.repeat("-", 60);

【讨论】:

... 并获得 3Mb 的新依赖项。 @MonoThreaded 我认为这是不言而喻的,但不要仅仅为了重复字符串而包含番石榴。我的回答是,如果您已经在使用番石榴,那么您就是这样做的。【参考方案8】:

使用java-8,您还可以使用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());

【讨论】:

... 或 return IntStream.range(0, times).mapToObj(i -&gt; str).collect(joining()); 更好地并行化 Stream.of(new String[times]).map(n -> "abc").collect(Collectors.joining());【参考方案9】:

所以你想避免循环?

给你:

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 开始),第二个是要重复的字符串。

到目前为止,快速检查使用不同输入运行的时间后,排名如下(从好到坏):

    迭代 StringBuilder 追加 (1x)。 递归串联 log2 调用 (~3x)。 递归串联线性调用 (~30x)。 迭代串联线性 (~45x)。

我从没想过递归函数比for 循环更快:-o

玩得开心(实用xD)。

【讨论】:

+1 表示递归,显然是一个 lisp 黑客。我认为这也不是那么低效,字符串连接不再是曾经的战争罪行,因为 + 真的只是一个 stringBuilder UTH。请参阅 ***.com/questions/47605/java-string-concatenation 和 schneide.wordpress.com/2009/02/23/… 。我想知道所有这些堆栈从递归成本中推送和弹出多少,或者热点是否会处理它们。真希望我有空闲时间对其进行基准测试。也许还有其他人? @e5:fortran 是对的;这个解决方案可以提高效率。此实现将不必要地为每个递归创建一个新的 StringBuilder(和一个新的 String)。不过仍然是一个不错的解决方案。 @e5 我希望我是一个 Lisp 黑客 xD...如果我是,我会使用尾递归函数:-p 微基准在 Java 中不能很好地工作。尝试这样衡量你的实现速度并不好。 @tecnotron 我知道,但它们总比没有好......唯一的“惊喜”是天真的循环连接和线性递归之间的细微差别。【参考方案10】:

这包含的字符少于您的问题

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

【讨论】:

它包含的字符比我的答案 StringUtils.repeat(str, n) 多。 除非您已经在使用 Apache Commons,否则这个答案会少很多麻烦 - 无需下载其他库,包括在您的类路径中,确保其许可证与您的兼容,等等。 请永远不要返回 null - 在这种情况下返回一个空字符串,允许您始终使用未选中的返回值。否则,我会推荐海报使用。 好吧,如果 s 为空,有三种处理方式。 1. 传递错误(返回 null), 2. 隐藏错误(返回 ""), 3. 抛出 NPE。隐藏错误并抛出 NPE 并不酷,所以我通过了错误。 @EthanHeilman 加上 2MB 的 commons-lang3.3.1-sources,你就不再那么好了;)但如果有人已经有 commons-lang,我支持你的回答。【参考方案11】:

基于fortran's answer,这是一个使用 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();

【讨论】:

循环而不是递归会减少大量重复的堆栈帧数。【参考方案12】:

使用Dollar 很简单:

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

PS:repeat也适用于数组、List、Set等

【讨论】:

真的需要assertThat()方法吗?【参考方案13】:

我想要一个函数来为 JDBC 目的创建一个逗号分隔的问号列表,并找到了这篇文章。所以,我决定采用两种变体,看看哪一种表现更好。经过 100 万次迭代后,普通的 StringBuilder 用了 2 秒(fun1),而神秘的据说更优化的版本(fun2)用了 30 秒。又神秘又有何意义?

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

【讨论】:

我觉得第二个需要更长的时间。它正在执行字符串搜索,然后逐个字符地修改字符串。【参考方案14】:

OOP 解决方案

几乎每个答案都提出了一个静态函数作为解决方案,但是考虑到面向对象(为了可重用性和清晰性)我想出了一个通过 CharSequence-Interface 委托的解决方案(这也打开了可变 CharSequence 的可用性-类)。

以下类可以在有或没有分隔符字符串/字符序列的情况下使用,并且每次调用“toString()”都会构建最终的重复字符串。 Input/Separator 不仅限于 String-Class,还可以是所有实现 CharSequence 的 Class(例如 StringBuilder、StringBuffer 等)!

源代码:

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

使用示例:

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

示例输出:

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

【讨论】:

我很少看到恶心的东西:/【参考方案15】:

仅使用 JRE 类 (System.arraycopy) 并尽量减少临时对象的数量,您可以编写如下代码:

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

编辑

如果没有循环,您可以尝试:

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(", ", "");

编辑 2

使用Collections 更短:

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

不过我还是喜欢第一个版本。

【讨论】:

-1:太聪明了一半。如果您的目标是使您的代码可读或高效,那么这些“解决方案”不是一个好主意。 'repeat' 可以简单地使用 StringBuilder 重写(设置初始容量)。而 'repeat2' / 'repeat3' 确实效率低下,并且依赖于 String[].toString() 产生的字符串的未指定语法。 @Thorb: 绝对,在这段代码中你不能使用“元字符”,[], @Stephen:问题已被编辑为明确地请求没有循环。已经提供了基于 StringBuilder 的答案,因此我避免重复发布 @Stephan:我想不出反对票。我编辑的答案是无循环的。没有关于效率的要求。我认为这个问题只是智力上的努力来产生一个没有循环的连接。 @Stephan:通过 Collection.toString(和 Arrays.toString)生成的字符串在 AbstractCollection.toString 中明确指定:“字符串表示由集合元素的列表组成按其迭代器返回的顺序,用方括号 ("[]") 括起来。相邻元素由字符 ", "(逗号和空格)分隔。"【参考方案16】:

不是最短的,但(我认为)最快的方法是使用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();
  

【讨论】:

【参考方案17】:

如果您关心的是速度,那么您应该尽可能少地使用内存复制。因此需要使用字符数组。

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

为了测试速度,使用 StirngBuilder 的类似优化方法是这样的:

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

以及测试它的代码:

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


这里是我系统的运行结果:

elapsed repeatString: 6006571
elapsed repeatStringSB: 9064937

请注意,循环测试是在 JIT 中启动并获得最佳结果。

【讨论】:

【参考方案18】:

一个简单的单行解决方案: 需要 Java 8

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

【讨论】:

【参考方案19】:

为了可读性和可移植性:

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

【讨论】:

【参考方案20】:

如果您担心性能,只需在循环内使用 StringBuilder 并在循环退出时执行 .toString() 。哎呀,编写自己的 Util 类并重用它。最多 5 行代码。

【讨论】:

【参考方案21】:

我真的很喜欢这个问题。有很多知识和风格。所以我不能不展示我的摇滚乐就离开它;)


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

你喜欢吗?

【讨论】:

在我更极端的测试中,我使用 -Xms4937m 生成了 1,700,000,000 (1.7 gigas) 的字符串重复长度【参考方案22】:
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);

【讨论】:

【参考方案23】:

简单循环

public static String repeat(String string, int times) 
    StringBuilder out = new StringBuilder();
    while (times-- > 0) 
        out.append(string);
    
    return out.toString();

【讨论】:

times 传递给 StringBuilder 构造函数。【参考方案24】:

试试这个:

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;

【讨论】:

【参考方案25】:

使用递归,您可以执行以下操作(使用三元运算符,最多一行):

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

我知道,它很丑而且可能效率不高,但它是一条线!

【讨论】:

这是我会采取的方法,但为什么要进行比需要更多的检查?返回数 > 0 ?字符串 + 重复(字符串,数字 1):“”; 哦,似乎niczm25在下面回答了它 @Fering 的主要原因,所以这种方式是 O(log N) 平均而不是 O(N) 总是。比另一个优化了一些,但仍然很糟糕。【参考方案26】:

如果你只知道输出字符串的长度(并且可能不能被输入字符串的长度整除),那么使用这个方法:

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

使用演示:

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

不要与空的slength > 0 一起使用,因为在这种情况下不可能得到想要的结果。

【讨论】:

【参考方案27】:

尽管您不想使用循环,但我认为您应该使用循环。

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

您不使用 for 循环的理由并不好。针对您的批评:

    无论您使用什么解决方案,几乎肯定会比这更长。使用预建函数只会将其隐藏在更多的掩护之下。 阅读您的代码的人必须弄清楚您在该非 for 循环中正在做什么。鉴于 for 循环是执行此操作的惯用方式,那么确定您是否使用 for 循环执行此操作会容易得多。 是的,有人可能会添加一些聪明的东西,但是通过避免 for 循环正在做一些聪明的事情。这就像故意向自己的脚开枪一样,以避免意外地向自己的脚开枪。 一个错误也很容易通过单个测试来捕获。鉴于您应该测试您的代码,一个错误的错误应该很容易修复和捕获。值得注意的是:上面的代码不包含一个错误。 For 循环同样容易正确。 所以不要重复使用变量。这不是 for 循环的错。 再说一次,无论您使用什么解决方案,都是如此。正如我之前提到的;错误猎人可能希望您使用 for 循环来执行此操作,因此如果您使用 for 循环,他们会更容易找到它。

【讨论】:

-1。这里有两个练习给你:a) 用repetitions = -5 运行你的代码。 b) 下载 Commons Lang 并循环运行repeatString('a', 1000) 一百万次;对您的代码执行相同的操作;比较时代。要获得额外的积分,请使用 repeatString('ab', 1000) 您是否认为您的代码比StringUtils.repeat("ab",1000) 更具可读性?因为那是我的回答,你投了反对票。它的性能也更好,没有错误。 阅读您引用的问题中的第二句话。 “我试图不惜一切代价避免 for 循环,因为”被添加到问题中,作为在我回复后回应 Andrew Hare 的回答的澄清 - 这并不重要,因为如果你所采取的立场是“如果循环是,则答案很糟糕使用过anywhere” OP 问题没有答案。即使是 dfa 的解决方案——尽管它们很有创意——也使用 for 内部循环。上面回复了“jar hell”;无论如何,commons lang 在每个体面大小的应用程序中都使用,因此不会添加新的依赖项。 @ChssPly76 在这一点上,我很确定 imagist 是在拖钓。我真的很难看到任何人都可以阅读我写的内容并认真思考上面输入的回复。 @ChssPly76 我的答案根本没有任何循环:-p【参考方案28】:

这里是最新的 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();
    
    

它甚至不需要这么大,可以做成这个,并且可以复制和粘贴 进入项目中的实用程序类。

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

所以 e5,我认为最好的方法是简单地使用上述代码或此处的任何答案。但是如果是一个小项目,commons lang 就太大了

【讨论】:

我不认为你可以做很多其他事情......也许是 AOT !【参考方案29】:

我创建了一个递归方法,它可以做你想做的事情......随意使用它......

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

我在Can I multiply strings in java to repeat sequences?有同样的答案

【讨论】:

不必要的字符串重新分配和递归开销......不好,不好,不好。 这会很慢。不建议!请改用StringBuilder【参考方案30】:
public static String rep(int a,String k)

       
           if(a<=0)
                return "";
           else 
           a--;
               return k+rep(a,k);
       

您可以将这种递归方法用于您想要的目标。

【讨论】:

以上是关于重复字符串的简单方法的主要内容,如果未能解决你的问题,请参考以下文章

在Python中击败字符串实习的最简单方法[重复]

有没有一种简单的方法可以返回重复 X 次的字符串?

从.net中的字符串获取十六进制的简单方法[重复]

在Java 8中将整数数组转换为字符串数组的最简单方法[重复]

判断数组是不是有重复,数组去重的简单方法

生成随机数的简单方法