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

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

repeated.equals("abcabcabc");

相关:

重复字符串javascript 通过重复给定次数的另一个字符串创建NSString

编辑

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

They add to the number of lines of code even if they are tucked away in another function. 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". 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". They are very often easy to get wrong. For loops involving indexes tend to generate off by one bugs. For loops often reuse the same variables, increasing the chance of really hard to find scoping bugs. For loops increase the number of places a bug hunter has to look.


当前回答

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

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循环的理由并不充分。针对你的批评:

Whatever solution you use will almost certainly be longer than this. Using a pre-built function only tucks it under more covers. 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. 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. 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. So don't reuse variables. That's not the for-loop's fault. 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.

其他回答

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

我想要一个函数来为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);
}

合并以供快速参考:

public class StringRepeat {

// Java 11 has built-in method - str.repeat(3);
// Apache - StringUtils.repeat(3);
// Google - Strings.repeat("",n);
// System.arraycopy

static String repeat_StringBuilderAppend(String str, int n) {

    if (str == null || str.isEmpty())
        return str;

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < n; i++) {
        sb.append(str);
    }
    return sb.toString();
}

static String repeat_ArraysFill(String str, int n) {
    String[] strs = new String[n];
    Arrays.fill(strs, str);
    return Arrays.toString(strs).replaceAll("\\[|\\]|,| ", "");
}

static String repeat_Recursion(String str, int n) {
    if (n <= 0)
        return "";
    else
        return str + repeat_Recursion(str, n - 1);
}

static String repeat_format1(String str, int n) {
    return String.format(String.format("%%%ds", n), " ").replace(" ", str);
}

static String repeat_format2(String str, int n) {
    return new String(new char[n]).replace("\0", str);
}

static String repeat_format3(String str, int n) {
    return String.format("%0" + n + "d", 0).replace("0", str);
}

static String repeat_join(String str, int n) {
    return String.join("", Collections.nCopies(n, str));
}

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

public static void main(String[] args) {
    System.out.println(repeat_StringBuilderAppend("Mani", 3));
    System.out.println(repeat_ArraysFill("Mani", 3));
    System.out.println(repeat_Recursion("Mani", 3));
    System.out.println(repeat_format1("Mani", 3));
    System.out.println(repeat_format2("Mani", 3));
    System.out.println(repeat_format3("Mani", 3));
    System.out.println(repeat_join("Mani", 3));
    System.out.println(repeat_stream("Mani", 3));

}

}

简单明了的解决方案: 需要Java 8

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

Commons only StringUtils.repeat()

用法:

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

repeated.equals("abcabcabc");