我正在寻找一个简单的公共方法或运算符,它允许我重复一些字符串n次.我知道我可以使用for循环来编写它,但我希望在必要时避免使用循环,并且某处应该存在一个简单的直接方法.
String str = "abc";
String repeated = str.repeat(3);
repeated.equals("abcabcabc");
Run Code Online (Sandbox Code Playgroud)
相关:
repeat string javascript 通过重复给定次数的另一个字符串来创建NSString
编辑
当他们不是完全必要的时候我试着避免循环,因为:
即使它们隐藏在另一个函数中,它们也会增加代码行数.
读我的代码的人必须弄清楚我在循环中做了什么.即使它被评论并且具有有意义的变量名称,它们仍然必须确保它没有做任何"聪明"的事情.
程序员喜欢把聪明的东西放在for循环中,即使我把它写成"只做它想要做的事情",这并不排除有人出现并增加一些额外的聪明"修复".
他们经常容易出错.对于涉及索引的循环,往往会产生一个错误.
For循环经常重用相同的变量,增加了很难找到范围错误的机会.
For循环增加了bug猎人必须看的地方数量.
use*_*008 862
这是最短的版本(需要Java 1.5+):
repeated = new String(new char[n]).replace("\0", s);
Run Code Online (Sandbox Code Playgroud)
n您想要重复字符串的次数在哪里,是要重复的字符串s.
不需要导入或库.
Chs*_*y76 307
Commons Lang StringUtils.repeat()
用法:
String str = "abc";
String repeated = StringUtils.repeat(str, 3);
repeated.equals("abcabcabc");
Run Code Online (Sandbox Code Playgroud)
Can*_*ner 287
如果您使用Java <= 7,这很简单:
// create a string made up of n copies of string s
String.format("%0" + n + "d", 0).replace("0", s);
Run Code Online (Sandbox Code Playgroud)
在Java 8及更高版本中,有一种简单的方法:
// create a string made up of n copies of string s
String.join("", Collections.nCopies(n, s));
Run Code Online (Sandbox Code Playgroud)
Java 11repeat?(int count)专门为此添加了一种新方法(链接)
int n = 3;
"abc".repeat(n);
Run Code Online (Sandbox Code Playgroud)
Nic*_*lai 167
从Java 11开始,有一种方法String::repeat可以完全满足您的要求:
". ".repeat( 7 ) // Seven period-with-space pairs: . . . . . . .
Run Code Online (Sandbox Code Playgroud)
String str = "abc";
String repeated = str.repeat(3);
repeated.equals("abcabcabc");
Run Code Online (Sandbox Code Playgroud)
Boa*_*ann 134
Java 8 String.join提供了一种结合以下方式执行此操作的简洁方法Collections.nCopies:
// say hello 100 times
System.out.println(String.join("", Collections.nCopies(100, "hello")));
Run Code Online (Sandbox Code Playgroud)
I. *_*edy 100
这是一种只使用标准String函数而不使用显式循环的方法:
// create a string made up of n copies of s
repeated = String.format(String.format("%%%ds", n), " ").replace(" ",s);
Run Code Online (Sandbox Code Playgroud)
Jac*_*ack 84
如果你像我一样想要使用Google Guava而不是Apache Commons.您可以在Guava Strings类中使用repeat方法.
Strings.repeat("-", 60);
Run Code Online (Sandbox Code Playgroud)
Ale*_* C. 49
使用java-8,您也可以使用Stream.generate.
import static java.util.stream.Collectors.joining;
...
String repeated = Stream.generate(() -> "abc").limit(3).collect(joining()); //"abcabcabc"
Run Code Online (Sandbox Code Playgroud)
如果需要,您可以将其包装在一个简单的实用程序方法中:
public static String repeat(String str, int times) {
return Stream.generate(() -> str).limit(times).collect(joining());
}
Run Code Online (Sandbox Code Playgroud)
for*_*ran 32
所以你想避免循环?
在这里你有:
public static String repeat(String s, int times) {
if (times <= 0) return "";
else return s + repeat(s, times-1);
}
Run Code Online (Sandbox Code Playgroud)
(当然我知道这是丑陋和低效的,但它没有循环:-p)
你想要它更简单,更漂亮吗?使用jython:
s * 3
Run Code Online (Sandbox Code Playgroud)
编辑:让我们稍微优化一下:-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);
}
Run Code Online (Sandbox Code Playgroud)
编辑2:我已经为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();
}
}
Run Code Online (Sandbox Code Playgroud)
它需要2个参数,第一个是迭代次数(每个函数以1..n的重复次数arg运行),第二个是要重复的字符串.
到目前为止,快速检查使用不同输入运行的时间使得排名类似于此(更好或更糟):
我不会猜到递归函数比for循环更快:-o
玩得开心(ctional xD).
Pyr*_*cal 20
这包含的字符少于您的问题
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();
}
Run Code Online (Sandbox Code Playgroud)
根据fortran的回答,这是一个使用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();
}
Run Code Online (Sandbox Code Playgroud)
使用Dollar很简单,因为输入:
@Test
public void repeatString() {
String string = "abc";
assertThat($(string).repeat(3).toString(), is("abcabcabc"));
}
Run Code Online (Sandbox Code Playgroud)
PS:重复也适用于数组,List,Set等
小智 7
我想要一个函数为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);
}
Run Code Online (Sandbox Code Playgroud)
小智 7
几乎每个答案都提出了一个静态函数作为解决方案,但是考虑面向对象(为了可重用性和清晰度),我通过CharSequence-Interface通过委派提出了一个解决方案(这也开启了可变CharSequence-Classes的可用性).
以下类可以使用或不使用Separator-String/CharSequence,每次调用"toString()"都会构建最终重复的String.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);
}
}
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
Repeat=2 Separator=<= Input=123 Length=3
CharSeq: Length=8 Val=123<=123
String : Length=8 Val=123<=123
123ff<=123ff
123ff<====>123ff
Run Code Online (Sandbox Code Playgroud)
仅使用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);
}
Run Code Online (Sandbox Code Playgroud)
编辑
没有循环你可以尝试:
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(", ", "");
}
Run Code Online (Sandbox Code Playgroud)
编辑2
使用集合甚至更短:
public static String repeat3(String toRepeat, int times) {
return Collections.nCopies(times, toRepeat).
toString().
replace("[", "").
replace("]", "").
replaceAll(", ", "");
}
Run Code Online (Sandbox Code Playgroud)
不过我还是喜欢第一个版本.
如果您关心速度,则应使用尽可能少的内存复制。因此,需要使用字符数组。
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);
}
Run Code Online (Sandbox Code Playgroud)
为了测试速度,使用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();
}
Run Code Online (Sandbox Code Playgroud)
和测试它的代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
这是我的系统的运行结果:
elapsed repeatString: 6006571
elapsed repeatStringSB: 9064937
Run Code Online (Sandbox Code Playgroud)
请注意,对循环的测试是启动JIT并获得最佳结果。
不是最短的,但是(我认为)最快的方法是使用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();
}
Run Code Online (Sandbox Code Playgroud)
一个简单的单行解决方案:
需要 Java 8
Collections.nCopies( 3, "abc" ).stream().collect( Collectors.joining() );
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
453207 次 |
| 最近记录: |