Simple way to repeat a string - java
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:
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.
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.
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);
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
*/
Commons Lang StringUtils.repeat()
Usage:
String str = "abc";
String repeated = StringUtils.repeat(str, 3);
repeated.equals("abcabcabc");
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")));
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);
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);
With java-8, 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());
}
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):
Iterative StringBuilder append (1x).
Recursive concatenation log2 invocations (~3x).
Recursive concatenation linear invocations (~30x).
Iterative concatenation linear (~45x).
I wouldn't ever guessed that the recursive function was faster than the for loop :-o
Have fun(ctional xD).
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();
}
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();
}
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
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);
}
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
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.
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();
}
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.
a straightforward one-line solution:
requires Java 8
Collections.nCopies( 3, "abc" ).stream().collect( Collectors.joining() );
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);
}
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.
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?
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);
}
Simple loop
public static String repeat(String string, int times) {
StringBuilder out = new StringBuilder();
while (times-- > 0) {
out.append(string);
}
return out.toString();
}
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;
}
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!
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.
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:
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.
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
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?
public static String rep(int a,String k)
{
if(a<=0)
return "";
else
{a--;
return k+rep(a,k);
}
You can use this recursive method for you desired goal.
Related
Repeat the content of a String [duplicate]
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: 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.
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.
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);
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 */
Commons Lang StringUtils.repeat() Usage: String str = "abc"; String repeated = StringUtils.repeat(str, 3); repeated.equals("abcabcabc");
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")));
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);
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);
With java-8, 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()); }
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): Iterative StringBuilder append (1x). Recursive concatenation log2 invocations (~3x). Recursive concatenation linear invocations (~30x). Iterative concatenation linear (~45x). I wouldn't ever guessed that the recursive function was faster than the for loop :-o Have fun(ctional xD).
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(); }
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(); }
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
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); }
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
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.
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(); }
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.
a straightforward one-line solution: requires Java 8 Collections.nCopies( 3, "abc" ).stream().collect( Collectors.joining() );
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); }
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.
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?
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); }
Simple loop public static String repeat(String string, int times) { StringBuilder out = new StringBuilder(); while (times-- > 0) { out.append(string); } return out.toString(); }
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; }
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!
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.
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: 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.
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
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?
public static String rep(int a,String k) { if(a<=0) return ""; else {a--; return k+rep(a,k); } You can use this recursive method for you desired goal.
Copying Strings n times for a Java Beginner
I'm taking an AP Computer Science course at my school, and wanted to know how to answer this question: Write a method named copies that, given as arguments a string s and a nonnegative integer n, returns the string formed from concatenating n copies of s. I've tried this, but you can't multiply strings: public String copies (String s, int n) { int copyCount; copyCount = 0; while ( n > 0 ) { s = s * n; n = n - 1; } return s; } I know similar question has been answered before, but I'm looking for a way to do this using only if-statements and while loops. Our class hasn't gotten to anything past that so far, so if anybody knows how to do it like this, it would be much appreciated. UPDATE: I also need to be able to show "" when I use 0 as n.
Something like this should do what you need. UPDATED to show "" when n = 0 public String copies(String s int n) { StringBuilder sb = new StringBuilder(); if (n > 0) { int i = 0; while (i < n) { sb.append(s); i++; } } return sb.toString(); }
Here's one way to do it. String copies(String s, int n) { StringBuilder builder = new StringBuilder(); for (int count = 0; count < n; ++count) builder.append(s); return builder.toString(); } I chose to use a for instead of a while (for cleanliness), but you should be able to make any mods you need pretty easily :p
If you want to create int n copies of String s you should try something like this // Return a String, containing n copies of s. public static String copies(String s, int n) { // More then 0? if (n > 0) { StringBuilder sb = new StringBuilder(); int i = 0; while (i < n) { sb.append(s); i++; } return sb.toString(); } // Just return the input. return s; }
Which variants string reverse are better?
I'm wondering to know which program variant are better runtime? Both variants looks easy to implement. But what are better to use and in which cases? String reverse: public static String reverse(String s) { String rev = ""; for (int i = s.length() - 1; i >= 0; i--) rev += s.charAt(i); return rev; } StringBuilder reverse: public static String reverse(String s) { StringBuilder rev = new StringBuilder(); for (int i = s.length() - 1; i >= 0; i--) rev.append(s.charAt(i)); return rev.toString(); }
in your two cases :i prefer the second one because the compiler will convert the first one from : rev += s.charAt(i); to : (new StringBuilder()).append(rev).append(s.charAt(i)).toString(); But , see the worst case scenario : public class Main { public static void main(String[] args) { long now = System.currentTimeMillis(); slow(); System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms"); now = System.currentTimeMillis(); fast(); System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms"); } private static void fast() { StringBuilder s = new StringBuilder(); for(int i=0;i<100000;i++) s.append("*"); } private static void slow() { String s = ""; for(int i=0;i<100000;i++) s+="*"; } } the output will be : slow elapsed 173 ms fast elapsed 1 ms
Neither is really great considering you can just do: new StringBuilder(str).reverse().toString(); If you had to use one of the above though, then pick the StringBuilder reverse - with the first one you could well send the GC through the roof creating and disposing of as many string objects as you have characters.
String class in java is immutable and can't change in his life, and concatenation of two string create new String and return, but StringBuilder is a mutable sequence of characters that can change characters of string in memory, and using StringBuilder should be better. as another solution, you can convert string to char array and reverse array and finally convert to String char[] arr = s.toCharArray(); char tmp; int maxIndex = arr.length-1; for( int i = arr.length>>2; i>=0;i--) { tmp = arr[i]; arr[i] = arr[maxIndex-i]; arr[maxIndex-i] = tmp; } return new String(arr); for more information see javadoc: StringBuilder , String and look StringBuilder class source codes to understand want is really happen on appending a character
Some interesting details. We can write a recursive function to reverse a string and don't use any loops. Use the String method substring(): public static String reverse(String s) { int N = s.length(); if (N <= 1) return s; String a = s.substring(0, N/2); String b = s.substring(N/2, N); return reverse(b) + reverse(a); } How efficient is this method? This method has a linearithmic running time.
Sequence Count i.e suppose aabbbaaccd is string output should be a=2,b=3,a=2,c=2,d=1
As i have tried ,it gives ArrayIndexOutOfBounds Ecxeption and does not print last char please help me to find bug in my code.or is there any alternate public static void sequenceCount(String s) { int counter; int i=0; char c; char[] arr = s.toCharArray(); while(i<arr.length){ counter=0; c = arr[i]; while(c==arr[i]){ counter++; i++; } System.out.println("letter"+" "+c+":"+"number of times"+counter); } } As i am a novice to java my code may be inefficient
Your inner loop is not bound by the length of the array. Try: while(i < arr.length && c==arr[i]){ counter++; i++; }
This works - you need to ensure that your inner loop doesn't pass beyond the end of the string, and you need to always catch the last letter, too: public static void sequenceCount(String s) { char[] arr = s.toCharArray(); int i = 0, n = arr.length; while (i < n) { char c = arr[i]; int count = 0; do { ++i; ++count; } while (i < n && arr[i] == c); System.out.println("letter "+ c +":"+"number of times " + count); } }
My approach would be to use two for loops. The first for loop would run a loop with the decimal equivalent of A to Z. The second for loop would run a loop that runs through the entire character array/string (I'd prefer a string rather than a char array here) and check to see if that given value at that index is equal the the value ran by the first for loop. If they are equal than add one to count. Print. Don't forget to reset your counter after every run as well. Similar Topic can be found here: Counting letters in a string using two for-loops
While many answers here are O(n^2), I tried to do it within O(n) time using recursion. This is modified from existing code that I already had so I know the method returns an int, but I don't use it (it's left over from copied code - fix it as you see fit) public class CountCharSeqRecursive { private String test = "AAABBA"; // (3)A(2)B(1)A private StringBuilder runningString = new StringBuilder(); public static void main(String[] args) { CountCharSeqRecursive t = new CountCharSeqRecursive(); System.out.println(t.getEncryptedValue(t.test)); } public String getEncryptedValue(String seq){ int startIndex=0; this.createCounterSeq(seq.charAt(startIndex), seq, startIndex); return runningString.toString(); } private int createCounterSeq(char prev, String sequence, int currentIndex){ return createCounterSeq(prev, sequence, currentIndex, 0); } private int createCounterSeq(char prev, String sequence, int currentIndex, int count){ if(currentIndex<sequence.length()){ char current = sequence.charAt(currentIndex); if((prev^current) < 1){ ++count; }else { this.addToSequence(count, prev); count = 1; } return count += createCounterSeq(current, sequence, ++currentIndex, count); } this.addToSequence(count, prev); return count; } private void addToSequence(int count, char ch){ runningString.append("("+count+")").append(ch); } }
My solution using HashSet, Works for all cases of a non-empty string. public static void main(String[] args) { // TODO Auto-generated method stub HashSet<Character> set = new HashSet<Character>(); String input = "aabbcdeaab"; set.add(input.charAt(0)); int count = 1; StringBuilder output = new StringBuilder(""); for(int i=1;i<input.length();i++) { char next = input.charAt(i); if(set.contains(next)) { count++; }else { char prev = input.charAt(i-1); output.append(Character.toString(prev) + count ); set.remove(prev); set.add(next); count=1; } } output.append(Character.toString(input.charAt(input.length()-1)) + count ); System.out.println(output.toString()); }
How to increment a java String through all the possibilities?
I need to increment a String in java from "aaaaaaaa" to "aaaaaab" to "aaaaaac" up through the alphabet, then eventually to "aaaaaaba" to "aaaaaabb" etc. etc. Is there a trick for this?
You're basically implementing a Base 26 number system with leading "zeroes" ("a"). You do it the same way you convert a int to a base-2 or base-10 String, but instead of using 2 or 10, you use 26 and instead of '0' as your base, you use 'a'. In Java you can easily use this: public static String base26(int num) { if (num < 0) { throw new IllegalArgumentException("Only positive numbers are supported"); } StringBuilder s = new StringBuilder("aaaaaaa"); for (int pos = 6; pos >= 0 && num > 0 ; pos--) { char digit = (char) ('a' + num % 26); s.setCharAt(pos, digit); num = num / 26; } return s.toString(); } The basic idea then is to not store the String, but just some counter (int an int or a long, depending on your requirements) and to convert it to the String as needed. This way you can easily increase/decrease/modify your counter without having to parse and re-create the String.
The following code uses a recursive approach to get the next string (let's say, from "aaaa" to "aaab" and so on) without the need of producing all the previous combinations, so it's rather fast and it's not limited to a given maximum string length. public class StringInc { public static void main(String[] args) { System.out.println(next("aaa")); // Prints aab System.out.println(next("abcdzz")); // Prints abceaa System.out.println(next("zzz")); // Prints aaaa } public static String next(String s) { int length = s.length(); char c = s.charAt(length - 1); if(c == 'z') return length > 1 ? next(s.substring(0, length - 1)) + 'a' : "aa"; return s.substring(0, length - 1) + ++c; } } As some folks pointed out, this is tail recursive, so you can reformulate it replacing the recursion with a loop.
Increment the last character, and if it reaches Z, reset it to A and move to the previous characters. Repeat until you find a character that's not Z. Because Strings are immutable, I suggest using an array of characters instead to avoid allocating lots and lots of new objects. public static void incrementString(char[] str) { for(int pos = str.length - 1; pos >= 0; pos--) { if(Character.toUpperCase(str[pos]) != 'Z') { str[pos]++; break; } else str[pos] = 'a'; } }
you can use big integer's toString(radix) method like: import java.math.BigInteger; public class Strings { Strings(final int digits,final int radix) { this(digits,radix,BigInteger.ZERO); } Strings(final int digits,final int radix,final BigInteger number) { this.digits=digits; this.radix=radix; this.number=number; } void addOne() { number=number.add(BigInteger.ONE); } public String toString() { String s=number.toString(radix); while(s.length()<digits) s='0'+s; return s; } public char convert(final char c) { if('0'<=c&&c<='9') return (char)('a'+(c-'0')); else if('a'<=c&&c<='p') return (char)(c+10); else throw new RuntimeException("more logic required for radix: "+radix); } public char convertInverse(final char c) { if('a'<=c&&c<='j') return (char)('0'+(c-'a')); else if('k'<=c&&c<='z') return (char)(c-10); else throw new RuntimeException("more logic required for radix: "+radix); } void testFix() { for(int i=0;i<radix;i++) if(convert(convertInverse((char)('a'+i)))!='a'+i) throw new RuntimeException("testFix fails for "+i); } public String toMyString() { String s=toString(),t=""; for(int i=0;i<s.length();i++) t+=convert(s.charAt(i)); return t; } public static void main(String[] arguments) { Strings strings=new Strings(8,26); strings.testFix(); System.out.println(strings.number.toString()+' '+strings+' '+strings.toMyString()); for(int i=0;i<Math.pow(strings.radix,3);i++) try { strings.addOne(); if(Math.abs(i-i/strings.radix*strings.radix)<2) System.out.println(strings.number.toString()+' '+strings+' '+strings.toMyString()); } catch(Exception e) { System.out.println(""+i+' '+strings+" failed!"); } } final int digits,radix; BigInteger number; }
I'd have to agree with #saua's approach if you only wanted the final result, but here is a slight variation on it in the case you want every result. Note that since there are 26^8 (or 208827064576) different possible strings, I doubt you want them all. That said, my code prints them instead of storing only one in a String Builder. (Not that it really matters, though.) public static void base26(int maxLength) { buildWord(maxLength, ""); } public static void buildWord(int remaining, String word) { if (remaining == 0) { System.out.println(word); } else { for (char letter = 'A'; letter <= 'Z'; ++letter) { buildWord(remaining-1, word + letter); } } } public static void main(String[] args) { base26(8); }
I would create a character array and increment the characters individually. Strings are immutable in Java, so each change would create a new spot on the heap resulting in memory growing and growing. With a character array, you shouldn't have that problem...
Have an array of byte that contain ascii values, and have loop that increments the far right digit while doing carry overs. Then create the string using public String(byte[] bytes, String charsetName) Make sure you pass in the charset as US-ASCII or UTF-8 to be unambiguous.
Just expanding on the examples, as to Implementation, consider putting this into a Class... Each time you call toString of the Class it would return the next value: public class Permutator { private int permutation; private int permutations; private StringBuilder stringbuilder; public Permutator(final int LETTERS) { if (LETTERS < 1) { throw new IllegalArgumentException("Usage: Permutator( \"1 or Greater Required\" \)"); } this.permutation = 0; // MAGIC NUMBER : 26 = Number of Letters in the English Alphabet this.permutations = (int) Math.pow(26, LETTERS); this.stringbuilder = new StringBuilder(); for (int i = 0; i < LETTERS; ++i) { this.stringbuilder.append('a'); } } public String getCount() { return String.format("Permutation: %s of %s Permutations.", this.permutation, this.permutations); } public int getPermutation() { return this.permutation; } public int getPermutations() { return this.permutations; } private void permutate() { // TODO: Implement Utilising one of the Examples Posted. } public String toString() { this.permutate(); return this.stringbuilder.toString(); } }
Building on the solution by #cyberz, the following code is an example of how you could write a recursive call which can be optimized by a compiler that supports Tail Recursion. The code is written in Groovy, since it runs on the JVM, its syntax closely resembles Java and it's compiler supports tail recursion optimization static String next(String input) { return doNext(input, "") } #TailRecursive #CompileStatic static String doNext(String input, String result) { if(!self) { return result } final String last = input[-1] final String nonLast = self.substring(0, input.size()-1) if('z' == last) { return doNext(nonLast, (nonLast ? 'a' : 'aa') + result) } return doNext('', nonLast + (((last as Character) + 1) as Character).toString() + result) }
Since none of the answers were useful to me, I wrote my own code: /** * Increases the given String value by one. Examples (with min 'a' and max 'z'): <p> * * - "aaa" -> "aab" <br> * - "aab" -> "aac" <br> * - "aaz" -> "aba" <br> * - "zzz" -> "aaaa" <br> * * #param s * #param min lowest char (a zero) * #param max highest char (e.g. a 9, in a decimal system) * #return increased String by 1 */ public static String incString(String s, char min, char max) { char last = s.charAt(s.length() - 1); if (++last > max) return s.length() > 1 ? incString(s.substring(0, s.length()-1), min, max) + min : "" + min + min; else return s.substring(0, s.length()-1) + last; }
public static String incrementString(String string) { if(string.length()==1) { if(string.equals("z")) return "aa"; else if(string.equals("Z")) return "Aa"; else return (char)(string.charAt(0)+1)+""; } if(string.charAt(string.length()-1)!='z') { return string.substring(0, string.length()-1)+(char)(string.charAt(string.length()-1)+1); } return incrementString(string.substring(0, string.length()-1))+"a"; } Works for all standard string containing alphabets
I have approach using for loop which is fairly simple to understand. based on [answer]: https://stackoverflow.com/a/2338415/9675605 cyberz answer. This also uses org.apache.commons.lang3.ArrayUtils. to insert letter on first position. you can create your own util for it. If someone finds helpful. import org.apache.commons.lang3.ArrayUtils; public class StringInc { public static void main(String[] args) { System.out.println(next("aaa")); // Prints aab System.out.println(next("abcdzz")); // Prints abceaa System.out.println(next("zzz")); // Prints aaaa } public static String next(String str) { boolean increment = true; char[] arr = str.toCharArray(); for (int i = arr.length - 1; i >= 0 && increment; i--) { char letter = arr[i]; if (letter != 'z') { letter++; increment = false; } else { letter = 'a'; } arr[i] = letter; } if (increment) { arr = ArrayUtils.insert(0, arr, 'a'); } return new String(arr); }
It's not much of a "trick", but this works for 4-char strings. Obviously it gets uglier for longer strings, but the idea is the same. char array[] = new char[4]; for (char c0 = 'a'; c0 <= 'z'; c0++) { array[0] = c0; for (char c1 = 'a'; c1 <= 'z'; c1++) { array[1] = c1; for (char c2 = 'a'; c2 <= 'z'; c2++) { array[2] = c2; for (char c3 = 'a'; c3 <= 'z'; c3++) { array[3] = c3; String s = new String(array); System.out.println(s); } } } }