repeat the string sequence until it reaches a certain length in java - java

I have two strings plainText and key. Now, if the plainText.length > key.length then i have to repeat the key until its the same length as that of plainText. here's an example:
plainText = "helloworld"
key="foobar"
hence the key should be increased to "foobarfoob".
One solution is to repeat the entire word and then remove the last characters until it reaches the same length as of plainText like "foobarfoobar" and then remove the characters "ar" .
Is there any better (or rather and Elegant) way to do this in java?

Your solution seems reasonable, other than the way you remove the last characters - don't do it one at a time, just use substring or StringBuilder.setLength():
// Make sure we never have to expand...
StringBuilder builder = new StringBuilder(plainText.length() + key.length() - 1);
while (builder.length() < plainText.length()) {
builder.append(key);
}
builder.setLength(plainText.length());
String result = builder.toString();
Or just change the append call to only get to the right size:
StringBuilder builder = new StringBuilder(plainText.length());
while (builder.length() < plainText.length()) {
builder.append(key.substring(0, Math.min(key.length(),
builder.length() - plainText.length()));
}
String result = builder.toString();
Personally I prefer the first - it's simpler.

My proposal (admittedly not very self-explanatory, but compact and efficient) - it repeats key as many times as necessary + 1 and uses substring to remove the extra characters:
public static void main(String[] args) throws Exception {
String plainText = "helloworld";
String key = "foobar";
int repeat = plainText.length() / key.length();
int remainder = plainText.length() % key.length();
String result = new String(new char[repeat + 1]).replaceAll(".", key).substring(0, key.length() * repeat + remainder);
System.out.println(result);
}

you can loop over key and in every step count the steps(which should be some time equal to plaintext => stop) and add those chars of every step to key. this is done in one loop

Related

Reducing run time in java

Below Java code produces the valid output but it takes more time to execute. Code works fine in eclipse, but it do not work in an online compiler like hackerrank or hackerearth since it takes more time for execution.Someone help me to find the solution for my time complexity problem.
I have tried to find the solution of the problem but i wasn't able to fix the performance by reducing the time..
Scanner scan = new Scanner(System. in );
String s = "aab";
String s1 = "";
String s2 = "";
int n1 = 0;
int length = 0;
long n = 882787;
long count = 0;
while (s1.length() < n) {
s1 = s1 + s;
}
if (s1.length() > n) {
count = s1.length() - n;
n1 = (int) count;
}
for (int i = 0; i < s1.length() - n1; i++) {
if (s1.charAt(i) == 'a') {
length += 1;
}
}
System.out.println(length);
Explanation of the above program:
I have a string s,in lowercase English letters that .I have repeat the string for n times and I store it in the new string.
I have to find the number of occurrences of 'a' in my new string
How do i actually reduce the time complexity for the above program
Thanks in advance
I would use a regular expression to create a String based on the initial input consisting of only letter 'a'(s). Take the length of that String and multiply it by n. That is one line that looks like
System.out.println(s.replaceAll("[^a]+", "").length() * n);
You are going to add s to the string n/s.length() times, call this N:
int N = n / s.length();
Each time you add s to the string you are going to append the number of As in s:
int a = 0;
for (int i = 0; i < s.length(); ++i) {
a += s.charAt(i) == 'a' ? 1 : 0;
}
// Or int a = s.replaceAll("[^a]", "").length();
So multiple these together:
int length = a * N;
String is immutable. Modification of a string is in fact create a new String object and put both old and new String into Java String constant poom
If you don't want to change your algorithm, I'd suggest to use StringBuilder to improve the speed of the execution. Note that StringBuilder is not thread safe
String s="aab";
int n1 = 0;
StringBuilder sb1 = new StringBuilder();
int length=0;
long n=882787;
long count=0;
while(sb1.length() < n) {
sb1.append(s);
}
if(sb1.length()>n) {
count =sb1.length()-n;
n1=(int)count;
}
for(int i=0;i<sb1.length()- n1;i++) {
if(sb1.charAt(i)=='a') {
length+=1;
}
}
System.out.println(length);
From here
When to use which one :
If a string is going to remain constant throughout the program, then
use String class object because a String object is immutable. If a
string can change (example: lots of logic and operations in the
construction of the string) and will only be accessed from a single
thread, using a StringBuilder is good enough. If a string can change,
and will be accessed from multiple threads, use a StringBuffer because
StringBuffer is synchronous so you have thread-safety.
I see multiple possible optimizations:
a) One pattern that is not that good is creating lots of Strings through repeated string concatenation. Each "s1 = s1 + s;" creates a new instance of String which will be obsolet the next time the command runs (It increases the load, because the String instances will be additional work for the Garbage Collector).
b) Generally: If you find, that your algorithm takes too long, then you should think about a complete new way to solve the issue. So a different solution could be:
- You know the length you want to have (n) and the length of the small string (s1) that you use to create the big string. So you can calculate: How often will the small string be inside the target string? How many characters are left?
==> You can simply check the small string for the character you are looking for. That multiplied by the number how often the small string will be inside the big string is the first result that you get.
==> Now you need to check the substring of the small string that are missing.
Example: n=10, s1="aab", Looking for "a":
So first we check how often the s1 will fit into a new string of n Characters n/length(s1) => 3
So we check how often the "a" is inside "aab" -> 2
First result is 3*2 = 6
But we checked for 3*3 = 9 characters so far, but we want 10 characters. So we need to check n % length(s1) = 1 character of s1 and in this substring ("a"), wie have 1 a, so we have to add 1.
So the result is 7 which we got without building a big string (which is not required at all!)
Just check how many times the char occurs in the original and multiple it by n. Here's a simple way to do so without even using regex:
// take these as function input or w/e
String s = "aab";
String find = "a";
long n = 882787;
int count = s.length() - s.replaceAll(find, "").length();
System.out.println(count * n);

Having problems with splitting a String into max 1Mb size subStrings

I have to split a String into 1Mb size strings. With using UTF-8 as character encoding, some letters take up more than 1 byte, so for avoiding to split a character in the middle (for example 'á' is 2 byte, so can't 1 byte go to the end of one String, and 1 to the beggining of the next String)
public static List<String> cutString3(String original, int chunkSize, String encoding) throws UnsupportedEncodingException {
List<String> strings = new ArrayList<>();
final int end = original.length();
int from = 0;
int to = 0;
do {
to = (to + chunkSize > end) ? end : to + chunkSize;
String chunk = original.substring(from, to); // get chunk
while (chunk.getBytes(encoding).length > chunkSize) { // cut the chunk from the end
chunk = original.substring(from, --to);
}
strings.add(chunk); // add chunk to collection
from = to; // next chunk
} while (to < end);
return strings;
}
I'm using the above method to generate an example String:
private static String createDataSize(int msgSize) {
StringBuilder sb = new StringBuilder(msgSize);
for (int i = 0; i < msgSize; i++) {
sb.append("a");
}
return sb.toString();
}
Calling the method as the following:
String exampleString = createDataSize(1024*1024*3);
cutString(exampleString, 1024*1024, "UTF-8");
It has no problems, I get back 3 Strings, as the 3 megabyte String was splitted into 3, 1 megabyte String. But if I change the createDataSize() method's char to append 'á' to the example String, so it only stands from "áááááá..." the inner while loop in the cutString method takes forever, since it's removing every 'á' one by one, until it fits into the given size. How can I improve the inner while, or come up with something similiar solution? The String can be smaller than 1 megabyte, just not bigger!
Using the binary search logic would clearly fit your need.
Simply decrement faster, using only the half of the chunk size, if you still as some room, add an half of it, if not, remove and half. And so on.
A simpler solution would be to remove only the differences between chunk.getBytes(encoding).length and chunkSize. Then see how many byte you can still take if you want to fill it completly.

Convert middle substring to "*"

I have a string String email="rachitgulati26#gmail.com" so its length is 24.
I want result like rachit************il.com.That means 1/4 of initial same and last 1/4 same.
Just want to convert 1/2 from middle to * with the help of regEX.
Thanks
You could do something like this:
"rachitgulati26#gmail.com".replaceAll("(?<=.{5}).(?=.{5})", "*");
this will replace all characters to * apart from the first and last 5.
In response to your question, you could make this flexible like this:
String email = "rachitgulati26#gmail.com";
int i = email.length() / 4;
email = email.replaceAll("(?<=.{" + i + "}).(?=.{" + i + "})", "*");
Just a word of warning, if you were to start using this in production code, you probably want to create a way of caching these regexes, based on the value of i. This way is for demonstration of the pattern only, and will compile a regex Pattern each time it is used.
One way to do it is to create a string of '*'s that is the correct length, then concatenate on the surrounding parts of the original string. That way you don't have to do any looping:
public static String starize(String str){
char[] middle = new char[str.length()/2];
Arrays.fill(middle, '*');
return str.substring(0, str.length()/4)
+ String.copyValueOf(middle)
+ str.substring(3 * str.length() / 4);
}
You could convert to char array, process and convert back to String:
String email = "rachitgulati26#gmail.com";
char[] a = email.toCharArray();
for (int i = 0, j = a.length >> 2; i < a.length >> 1; i++, j++)
a[j] = '*';
email = new String(a);
Result:
rachit************il.com
You can't identify the middle of a string using a single regular expression unless the lengths have a finite number of values.

Algorithm for incrementing a String in a non-obvious manner

I want to create random-looking 5 or 6 character alpha-numeric strings, something like:
Vg78KY
Creating (pseudo-)random Strings has been answered, but I am wondering if there is an algorithm for incrementing a String in a non-obvious manner. A simple increment of the above String might yield:
Vg78KZ
But I don't want this next String to be guessable, I want it to look completely different. Of course, successive increments should not yield a previous result as each should be unique.
Any thoughts on how to achieve this much appreciated!
Thanks
An easy approach that avoids the need for lookup tables would be:
Increment an integer normally
Permute the bits in a non-obvious way (a fixed permutation is probably fine, but if you want something more sophisticated you could use something like George Marsaglia's XORShift algorithm that produces a psuedorandom sequence of integers that only repeats after a very long cycle)
Convert to Base64 encoded strings
If we assume there must be a 1:1 mapping from "sequence number" to "random-looking string", then the truncated hash approach will not work as there is no guarantee that the truncated hash won't be subject to collisions.
I'd do something like this:
Take the next integer in sequence.
Xor with a fixed number.
Permute the bits.
Encode the number using Base64, Base36, or whatever.
Note that this will be subject to easy analysis by a determined attacker with access to a sufficiently large set of sequence numbers.
What exactly do you mean by increment? If you just want some values that is the result of the original value, the you can use a hash code (possibly a cryptographic hash). Then simply encode it a way that uses the characters you want to use (for example Base64 or something similar) and cut it off at the number of characters you want.
This is a one-way operation, however. That means that you can easily get successor of a value, but can't easily get the predecessor.
import java.util.UUID;
public class RandomStringUUID {
public static void main(String[] args) {
UUID uuid = UUID.randomUUID();
String randomUUIDString = uuid.toString();
System.out.println("Random UUID String = " + randomUUIDString);
System.out.println("UUID version = " + uuid.version());
System.out.println("UUID variant = " + uuid.variant());
}
}
If you want to generate collision safe strings just use UUIDs
If you want it to be incremented it means you have some transformation function F() that transforms from one space to another.
So you probably have a function from {Z} -> {SomeString}
So what you need to do, is just apply the opposite of F() (F-1) to the string, get the original number, increment it, and generate it again.
in pseudocode:
int i = 1;
String s = Transform(i);
int num = UnTransform(s);
num++;
String next = Transform(num);
What about this one:
convert the number to binary format;
change the order of digits by fixed manual mapping (last digit to 6th place, etc);
convert the number back to hash
Another simple way to do this would be:
$hash_key = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
$hash_table = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
$init = 10000000;
$hash_value = str_replace($hash_key, $hash_table, strval($init));
//$hash_value = 'BAAAAAAA'
//For next value:
$init++;
$hash_value = str_replace($hash_key, $hash_table, strval($init));
//$hash_value = 'BAAAAAAB'
//If you want to increment only the string without knowing the digits:
$prev_hash = $hash_value;
$prev_init = intval(str_replace($hash_table, $hash_key, $prev_hash));
//$prev_init = 10000001
$next_init = $prev_init + 1;
$next_hash = str_replace($hash_key, $hash_table, strval($next_init));
//$next_hash = 'BAAAAAAC'
Hope this helps. :-)
One of possible solutions would be to pre-generate the entire dictionary of all possible strings and then use SecureRandom to point to an index of that dictionary. If a particular element would already be "reserved", you'd simply go to the next available one (this operation can also be pre-generated btw).
The obvious disadvantage of this solution is non-determinism. But this was not requested by OP. And I'm not even sure if determinism is possible in this situation.
Lazy method: keep a hashtable or set to store all existing strings, and each time you generate a random string, check to see if it's in the set. If so, generate a new one until you get one that's not in the set.
This would probably be both memory- and processor-intensive in the long run, though.
You might try and convert the following Python to the language of your choice...
>>> import string, random, itertools
>>> digits = list(string.ascii_lowercase + string.ascii_uppercase + string.digits + '_')
>>> ''.join(digits)
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
>>> digit_count = 4
>>> alldigits = [digits[:] for i in range(digit_count)]
>>> for d in alldigits: random.shuffle(d)
>>> numbergen = (''.join(d) for d in itertools.product(*alldigits))
>>> numbergen.__next__()
'B1xx'
>>> numbergen.__next__()
'B1x1'
>>> numbergen.__next__()
'B1xQ'
>>> numbergen.__next__()
'B1x7'
Well since you want the string to be alphanumeric, then it's pretty straightforward. Create a character array of size 62. This is 26 lowercase letters, 26 uppercase letters, and the 10 digits 0-9. After you fill in the array, loop through N times, where N is the length of your string, selecting a random index each time. So it should look something like this:
char [] arrayOfCharacters = new char[62];
int index = 0;
for(char a = 'a';a<= 'z';a++)
{
arrayOfCharacters[index++] = a;
}//copy this loop for the upper case characters and 0-9
String randomString = "";
for(int x = 0;x < N; x++)
{
randomString += arrayOfCharacters[(int)(Math.random() * arrayOfCharacters.length)];
}
That's my code.. it does exactly what you asked for using the UUID to generate a string then execute (-) from it.
import java.util.*;
class KeyGen {
public static void main(String[] args) {
String uuid = UUID.randomUUID().toString();
String str = uuid.replaceAll("[-]", "").toUpperCase();
String s = "";
Scanner scan = new Scanner(System.in);
String[] array = str.split("");
Random rnd = new Random();
int N = rnd.nextInt(str.length());
System.out.println("How many keys you want?");
int keys = scan.nextInt();
String[] rndstr = new String[keys];
System.out.println("How many letters for the first key?");
int count = scan.nextInt();
for (int t = 0; t < keys; t++)
{
s="";
count++;
for(int i=0; i < count; i++)
{
uuid = UUID.randomUUID().toString();
str = uuid.replaceAll("[-]", "").toUpperCase();
int len = str.length();
N= rnd.nextInt(len) + 1;
s = s + array[N];
}
rndstr[t] = s;
}
for (int j=0; j < rndstr.length; j++)
{
System.out.println(rndstr[j]);
}
}
}
Simple output:
How many keys you want?
4
How many letters for the first key?
6
Here are your keys:
5F2934A
C8A456A6
B06E49240
FE3AE40CCE
Make your string the result of a hash operation. For example, using your random strings as input:
String input1 = "Vg78KY";
String output1 = String.valueOf(input1.hashCode());
String input2 = "Vg78KZ";
String output2 = String.valueOf(input2.hashCode());
output1 and output2 will be completely different.

Create a string with n characters

Is there a way in Java to create a string with a specified number of a specified character? In my case, I would need to create a string with ten spaces. My current code is:
final StringBuffer outputBuffer = new StringBuffer(length);
for (int i = 0; i < length; i++){
outputBuffer.append(" ");
}
return outputBuffer.toString();
Is there a better way to accomplish the same thing? In particular, I'd like something that is fast (in terms of execution).
Likely the shortest code using the String API, exclusively:
String space10 = new String(new char[10]).replace('\0', ' ');
System.out.println("[" + space10 + "]");
// prints "[ ]"
As a method, without directly instantiating char:
import java.nio.CharBuffer;
/**
* Creates a string of spaces that is 'spaces' spaces long.
*
* #param spaces The number of spaces to add to the string.
*/
public String spaces( int spaces ) {
return CharBuffer.allocate( spaces ).toString().replace( '\0', ' ' );
}
Invoke using:
System.out.printf( "[%s]%n", spaces( 10 ) );
I highly suggest not to write the loop by hand.
You will do that over and over again during the course of your programming career.
People reading your code - that includes you - always have to invest time, even if it are just some seconds, to digest the meaning of the loop.
Instead reuse one of the available libraries providing code that does just that like StringUtils.repeatfrom Apache Commons Lang:
StringUtils.repeat(' ', length);
That way you also do not have to bother about performance, thus all the gory details of StringBuilder, Compiler optimisations etc. are hidden.
If the function would turn out as slow it would be a bug of the library.
With Java 11 it becomes even easier:
" ".repeat(length);
Hmm now that I think about it, maybe Arrays.fill:
char[] charArray = new char[length];
Arrays.fill(charArray, ' ');
String str = new String(charArray);
Of course, I assume that the fill method does the same thing as your code, so it will probably perform about the same, but at least this is fewer lines.
since Java 11:
" ".repeat(10);
since Java 8:
generate(() -> " ").limit(10).collect(joining());
where:
import static java.util.stream.Collectors.joining;
import static java.util.stream.Stream.generate;
The for loop will be optimized by the compiler. In such cases like yours you don't need to care about optimization on your own. Trust the compiler.
BTW, if there is a way to create a string with n space characters, than it's coded the same way like you just did.
In Java 8 you can use String.join:
String.join("", Collections.nCopies(n, s));
If you want only spaces, then how about:
String spaces = (n==0)?"":String.format("%"+n+"s", "");
which will result in abs(n) spaces;
Since Java 11 you can simply use String.repeat(count) to solve your problem.
Returns a string whose value is the concatenation of this string repeated count times.
If this string is empty or count is zero then the empty string is returned.
So instead of a loop your code would just look like this:
" ".repeat(length);
I think this is the less code it's possible, it uses Guava Joiner class:
Joiner.on("").join(Collections.nCopies(10, " "));
You can use standard String.format function for generate N spaces.
For example:
String.format("%5c", ' ');
Makes a string with 5 spaces.
or
int count = 15;
String fifteenSpacebars = String.format("%" + count + "c", ' ');
Makes a string of 15 spacebars.
If you want another symbol to repeat, you must replace spaces with your desired symbol:
int count = 7;
char mySymbol = '#';
System.out.println(String.format("%" + count + "c", ' ').replaceAll("\\ ", "\\" + mySymbol));
Output:
#######
My contribution based on the algorithm for fast exponentiation.
/**
* Repeats the given {#link String} n times.
*
* #param str
* the {#link String} to repeat.
* #param n
* the repetition count.
* #throws IllegalArgumentException
* when the given repetition count is smaller than zero.
* #return the given {#link String} repeated n times.
*/
public static String repeat(String str, int n) {
if (n < 0)
throw new IllegalArgumentException(
"the given repetition count is smaller than zero!");
else if (n == 0)
return "";
else if (n == 1)
return str;
else if (n % 2 == 0) {
String s = repeat(str, n / 2);
return s.concat(s);
} else
return str.concat(repeat(str, n - 1));
}
I tested the algorithm against two other approaches:
Regular for loop using String.concat() to concatenate string
Regular for loop using a StringBuilder
Test code (concatenation using a for loop and String.concat() becomes to slow for large n, so I left it out after the 5th iteration).
/**
* Test the string concatenation operation.
*
* #param args
*/
public static void main(String[] args) {
long startTime;
String str = " ";
int n = 1;
for (int j = 0; j < 9; ++j) {
n *= 10;
System.out.format("Performing test with n=%d\n", n);
startTime = System.currentTimeMillis();
StringUtil.repeat(str, n);
System.out
.format("\tStringUtil.repeat() concatenation performed in %d milliseconds\n",
System.currentTimeMillis() - startTime);
if (j <5) {
startTime = System.currentTimeMillis();
String string = "";
for (int i = 0; i < n; ++i)
string = string.concat(str);
System.out
.format("\tString.concat() concatenation performed in %d milliseconds\n",
System.currentTimeMillis() - startTime);
} else
System.out
.format("\tString.concat() concatenation performed in x milliseconds\n");
startTime = System.currentTimeMillis();
StringBuilder b = new StringBuilder();
for (int i = 0; i < n; ++i)
b.append(str);
b.toString();
System.out
.format("\tStringBuilder.append() concatenation performed in %d milliseconds\n",
System.currentTimeMillis() - startTime);
}
}
Results:
Performing test with n=10
StringUtil.repeat() concatenation performed in 0 milliseconds
String.concat() concatenation performed in 0 milliseconds
StringBuilder.append() concatenation performed in 0 milliseconds
Performing test with n=100
StringUtil.repeat() concatenation performed in 0 milliseconds
String.concat() concatenation performed in 1 milliseconds
StringBuilder.append() concatenation performed in 0 milliseconds
Performing test with n=1000
StringUtil.repeat() concatenation performed in 0 milliseconds
String.concat() concatenation performed in 1 milliseconds
StringBuilder.append() concatenation performed in 1 milliseconds
Performing test with n=10000
StringUtil.repeat() concatenation performed in 0 milliseconds
String.concat() concatenation performed in 43 milliseconds
StringBuilder.append() concatenation performed in 5 milliseconds
Performing test with n=100000
StringUtil.repeat() concatenation performed in 0 milliseconds
String.concat() concatenation performed in 1579 milliseconds
StringBuilder.append() concatenation performed in 1 milliseconds
Performing test with n=1000000
StringUtil.repeat() concatenation performed in 0 milliseconds
String.concat() concatenation performed in x milliseconds
StringBuilder.append() concatenation performed in 10 milliseconds
Performing test with n=10000000
StringUtil.repeat() concatenation performed in 7 milliseconds
String.concat() concatenation performed in x milliseconds
StringBuilder.append() concatenation performed in 112 milliseconds
Performing test with n=100000000
StringUtil.repeat() concatenation performed in 80 milliseconds
String.concat() concatenation performed in x milliseconds
StringBuilder.append() concatenation performed in 1107 milliseconds
Performing test with n=1000000000
StringUtil.repeat() concatenation performed in 1372 milliseconds
String.concat() concatenation performed in x milliseconds
StringBuilder.append() concatenation performed in 12125 milliseconds
Conclusion:
For large n - use the recursive approach
For small n - for loop has sufficient speed
How about this?
char[] bytes = new char[length];
Arrays.fill(bytes, ' ');
String str = new String(bytes);
Considering we have:
String c = "c"; // character to repeat, for empty it would be " ";
int n = 4; // number of times to repeat
String EMPTY_STRING = ""; // empty string (can be put in utility class)
Java 8 (Using Stream)
String resultOne = IntStream.range(0,n)
.mapToObj(i->c).collect(Collectors.joining(EMPTY_STRING)); // cccc
Java 8 (Using nCopies)
String resultTwo = String.join(EMPTY_STRING, Collections.nCopies(n, c)); //cccc
RandomStringUtils has a provision to create a string from given input size.
Cant comment on the speed, but its a one liner.
RandomStringUtils.random(5,"\t");
creates an output
\t\t\t\t\t
preferable if you dont want to see \0 in your code.
Use StringUtils:
StringUtils.repeat(' ', 10)
The shortest solution with Guava:
Strings.repeat(" ", len)
Via Simple way to repeat a String in java.
This worked out for me without using any external libraries in Java 8
String sampleText = "test"
int n = 3;
String output = String.join("", Collections.nCopies(n, sampleText));
System.out.println(output);
And the output is
testtesttest
int c = 10;
String spaces = String.format("%" +c+ "c", ' ');
this will solve your problem.
In most cases you only need Strings upto a certains length, say 100 spaces. You could prepare an array of Strings where the index number is equal to the size of the space-filled string and lookup the string, if the required length is within the limits or create it on demand if it's outside the boundary.
For good performance, combine answers from aznilamir and from FrustratedWithFormsDesigner
private static final String BLANKS = " ";
private static String getBlankLine( int length )
{
if( length <= BLANKS.length() )
{
return BLANKS.substring( 0, length );
}
else
{
char[] array = new char[ length ];
Arrays.fill( array, ' ' );
return new String( array );
}
}
Adjust size of BLANKS depending on your requirements. My specific BLANKS string is about 200 characters length.
Just replace your StringBuffer with a StringBuilder. Hard to beat that.
If your length is a big number, you might implement some more efficient
(but more clumsy) self-appendding, duplicating the length in each iteration:
public static String dummyString(char c, int len) {
if( len < 1 ) return "";
StringBuilder sb = new StringBuilder(len).append(c);
int remnant = len - sb.length();
while(remnant > 0) {
if( remnant >= sb.length() ) sb.append(sb);
else sb.append(sb.subSequence(0, remnant));
remnant = len - sb.length();
}
return sb.toString();
}
Also, you might try the Arrays.fill() aproach (FrustratedWithFormsDesigner's answer).
You can replace StringBuffer with StringBuilder ( the latter is not synchronized, may be a faster in a single thread app )
And you can create the StringBuilder instance once, instead of creating it each time you need it.
Something like this:
class BuildString {
private final StringBuilder builder = new StringBuilder();
public String stringOf( char c , int times ) {
for( int i = 0 ; i < times ; i++ ) {
builder.append( c );
}
String result = builder.toString();
builder.delete( 0 , builder.length() -1 );
return result;
}
}
And use it like this:
BuildString createA = new BuildString();
String empty = createA.stringOf( ' ', 10 );
If you hold your createA as a instance variable, you may save time creating instances.
This is not thread safe, if you have multi threads, each thread should have its own copy.
Have a method like this. This appends required spaces at the end of the given String to make a given String to length of specific length.
public static String fillSpaces (String str) {
// the spaces string should contain spaces exceeding the max needed
String spaces = " ";
return str + spaces.substring(str.length());
}
Want String to be of fixed size, so you either pad or truncate, for tabulating data...
class Playground {
private static String fixStrSize(String s, int n) {
return String.format("%-" + n + "s", String.format("%." + n +"s", s));
}
public static void main(String[ ] args) {
System.out.println("|"+fixStrSize("Hell",8)+"|");
System.out.println("|"+fixStrSize("Hells Bells Java Smells",8)+"|");
}
}
|Hell |
|Hells Be|
Excellent reference here.
A simple method like below can also be used
public static String padString(String str, int leng,char chr) {
for (int i = str.length(); i <= leng; i++)
str += chr;
return str;
}
how about this?
public String fillSpaces(int len) {
/* the spaces string should contain spaces exceeding the max needed */
String spaces = " ";
return spaces.substring(0,len);
}
EDIT: I've written a simple code to test the concept and here what i found.
Method 1: adding single space in a loop:
public String execLoopSingleSpace(int len){
StringBuilder sb = new StringBuilder();
for(int i=0; i < len; i++) {
sb.append(' ');
}
return sb.toString();
}
Method 2: append 100 spaces and loop, then substring:
public String execLoopHundredSpaces(int len){
StringBuilder sb = new StringBuilder(" ")
.append(" ").append(" ").append(" ")
.append(" ").append(" ").append(" ")
.append(" ").append(" ").append(" ");
for (int i=0; i < len/100 ; i++) {
sb.append(" ")
.append(" ").append(" ").append(" ")
.append(" ").append(" ").append(" ")
.append(" ").append(" ").append(" ");
}
return sb.toString().substring(0,len);
}
The result I get creating 12,345,678 spaces:
C:\docs\Projects> java FillSpace 12345678
method 1: append single spaces for 12345678 times. Time taken is **234ms**. Length of String is 12345678
method 2: append 100 spaces for 123456 times. Time taken is **141ms**. Length of String is 12345678
Process java exited with code 0
and for 10,000,000 spaces:
C:\docs\Projects> java FillSpace 10000000
method 1: append single spaces for 10000000 times. Time taken is **157ms**. Length of String is 10000000
method 2: append 100 spaces for 100000 times. Time taken is **109ms**. Length of String is 10000000
Process java exited with code 0
combining direct allocation and iteration always takes less time, on average 60ms less when creating huge spaces. For smaller sizes, both results are negligible.
But please continue to comment :-)
I know of no built-in method for what you're asking about. However, for a small fixed length like 10, your method should be plenty fast.

Categories