I was asked to write a method that was passed a String and then return a String with each character doubled. I found the code on a previously asked question, but what I was wondering is why the s.charAt(i) had to be added twice.
The code I used was:
public static String twoChars(String s){
String r= "";
for(int i=0; i<s.length(); i++)
r=r+s.charAt(i)+s.charAt(i);
return r;
}
If you follow the program logic, you will see that the following occurs:
1) pass a string (for example "hello")
2) start another empty string (String r = "")
3) when i==0, r becomes: ""+ h + h
4) when i==1, r becomes: hh + e + e
5) etc.
6) return "hheelloo"
NOTE: As was stated previously, using StringBuilder is a much better solution because strings are immutable (each time r is changed, a new string is created and thus wasting precious resources).
Because r is empty, The method adds each char twice to r before returns it. a better approach is to use StringBuilder for that :
public static String twoChars(String s){
StringBuilder sb=new StringBuilder();
for(int i=0; i<s.length(); i++)
sb.append(s.charAt(i)+ "" +s.charAt(i));
return sb.toString();
}
Well here's how to think about this and what to keep in mind.
First of all, String in Java is immutable. All modifications you are doing on a String will result in a new String being created. This may be a problem if you do a lot of modifications on a lot of strings, resulting in a massive memory usage. Always remember this, especially when you have loops where you change strings.
Now back to the problem. Given a String, s, you want to "double" every single character. Since you'll have to check every single character of s, you will probably need a loop.
What else do you need? Well, you need some sort of structure to build your new String. You can go either for StringBuilder or char[]. A StringBuilder does just that: builds strings. However, it builds then in a memory-efficient way. Actually internally it contains a char[].
Here's the StringBuilder solution:
String input = "hello";
StringBuilder builder = new StringBuilder(input.length() * 2);
for(int i = 0; i < input.length(); i++)
{
builder.append(input.charAt(i)).append(input.charAt(i));
}
String finalString = builder.toString();
Here's a char[] solution
String input = "hello";
char[] tempChar = new char[input.length() * 2];
for(int i = 0; i < input.length(); i++)
{
tempChar[2 * i] = input.charAt(i);
tempChar[2 * i + 1] = input.charAt(i);
}
String output = new String(tempChar);
Related
I want to achieve something like this.
String str = "This is just a sample string";
List<String> strChunks = splitString(str,8);
and strChunks should should be like:
"This is ","just a ","sample ","string."
Please note that string like "sample " have only 7 characters as with 8 characters it will be "sample s" which will break down my next word "string".
Also we can go with the assumption that a word will never be larger than second argument of method (which is 8 in example) because in my use case second argument is always static with value 32000.
The obvious approach that I can think of is looping thru the given string, breaking the string after 8 chars and than searching the next white space from the end. And then repeating same thing again for remaining string.
Is there any more elegant way to achieve the same. Is there any utility method already available in some standard third libraries like Guava, Apache Commons.
Splitting on "(?<=\\G.{7,}\\s)" produces the result that you need (demo).
\\G means the end of previous match; .{7,} means seven or more of any characters; \\s means a space character.
Not a standard method, but this might suit your needs
See it on http://ideone.com/2RFIZd
public static List<String> splitString(String str, int chunksize) {
char[] chars = str.toCharArray();
ArrayList<String> list = new ArrayList<String>();
StringBuilder builder = new StringBuilder();
int count = 0;
for(char character : chars) {
if(count < chunksize - 1) {
builder.append(character);
count++;
}
else {
if(character == ' ') {
builder.append(character);
list.add(builder.toString());
count = 0;
builder.setLength(0);
}
else {
builder.append(character);
count++;
}
}
}
list.add(builder.toString());
builder.setLength(0);
return list;
}
Please note, I used the human notation for string length, because that's what your sample reflects( 8 = postion 7 in string). that's why the chunksize - 1 is there.
This method takes 3 milliseconds on a text the size of http://catdir.loc.gov/catdir/enhancements/fy0711/2006051179-s.html
Splitting String using method 1.
String text="This is just a sample string";
List<String> strings = new ArrayList<String>();
int index = 0;
while (index < text.length()) {
strings.add(text.substring(index, Math.min(index + 8,text.length())));
index += 8;
}
for(String s : strings){
System.out.println("["+s+"]");
}
Splitting String using Method 2
String[] s=text.split("(?<=\\G.{"+8+"})");
for (int i = 0; i < s.length; i++) {
System.out.println("["+s[i]+"]");
}
This uses a hacked reduction to get it done without much code:
String str = "This is just a sample string";
List<String> parts = new ArrayList<>();
parts.add(Arrays.stream(str.split("(?<= )"))
.reduce((a, b) -> {
if (a.length() + b.length() <= 8)
return a + b;
parts.add(a);
return b;
}).get());
See demo using edge case input (that breaks some other answers!)
This splits after each space, then either joins up parts or adds to the list depending on the length of the pair.
I have String variable with value- f.e.:
this is test-str-ing_łóśżćń.
And I would like replace this chars:
, -, ł,ó,ś,ż,ć,ń
with those:
_,_,l,o,s,z,c,n.
And I mean here, that if parser will found f.e.: char - (which is second in first list) should be replaced with char that is in the same position/place in second list, which in this example is: _.
The char ó should be replaced with char o.
The char ń should be replaced with char n.
In my case the list of characters to replace is quite long and parsing in loop for each char to replace would not be enought efficient.
I know method replaceAll(). but it only accept one in String and one out String
So I am looking for method, that will allow me to work on arrays/list of Strings instead of single String.
Please give me some help.
Use java.text.Normalizer to Decompose accented letters in base letter plus "combining diacritical marks."
String base = Normalizer.normalize(accented, Form.NFKD)
.replaceAll("\\p{M}", "");
This does a decompose (D) normalization, and then removes Marks.
Some replacements still needed.
char[] out = new char[src.length()];
for( j ...){
inputChar = src.charAt(j);
for (int i = 0; i < convertChars.length; i++) {
if (inputChar == convertChars[i]) {
inputChar = toChars[i];
}
}
}
out[j] = inputChar ;
}
out2 = new String(out);
Extracted from bigger code without IDE, not tested. Loop (I hope) don't allocate objects and should not degrade speed.
Make a static lookup table:
private static char[] substitutions = new char[65536];
static {
// Initialize
for (char c = 0; c < substitutions.length; c++) {
substitutions[c] = c;
}
// Now add mappings.
substitions['-'] = '_'; // Map source->target character
... // Add the rest
}
// LATER IN Code
char[] stringChars = inputString.toCharArray();
for (int i = 0; i < stringChars.length; i++) {
stringChars[i] = substitutions[stringChars[i]];
}
outputString = new String(stringChars);
What is the problem in following example? what happens if millions of Char in the String to be Reversed?
public static String reverseUsingStringBuffer(String source) {
if(source == null || source.isEmpty()){
return source;
}
StringBuffer reverse = new StringBuffer();
for(int i = source.length() -1; i>=0; i--){
reverse.append(source.charAt(i));
}
return reverse.toString();
}
Is following better approach? (beside using api method). What is the good approach for huge String?
public static String reverse(String source) {
if(source == null || source.isEmpty()){
return source;
}
String reverse = "";
for(int i = source.length() -1; i>=0; i--){
reverse = reverse + source.charAt(i);
}
return reverse;
}
As already said, the String approach is pretty bad. Using StringBuffer is much better, but there's no reason for this rather obsolete class, when StringBuilder can do the same faster.
Even simpler and faster in this case is to use an array:
char[] result = new char[source.length];
for(int i = 0; i < source.length(); ++i) result[source.length() - 1 - i] = source.charAt(i);
return new String(result);
This allocates no garbage at all.... except for the char[], but this is unavoidable as String is immutable and the sharing constructor is package-private (for a good reason).
Note that usually there's absolutely no need to optimize that hard.
No, the first approach is better because it will internally manage your buffers for you. Don't try to outsmart the compiler. Why didn't you append the entire source in one line, which will properly allocate your buffer.
The first one. In the second you use "string = string + string" and this creates one object every time you use "+". I'd sugest StringBuffer.
The first approach is better, StringBuffer is mutable and using string = string+string decrease performance.
You can make it in place as well.
public static String reverse(String s) {
char[] chars = s.toCharArray();
for(int i = 0, j = chars.length - 1; i < chars.length / 2; i++, j--) {
char c = chars[i];
chars[i] = chars[j];
chars[j] = c;
}
return new String(chars);
}
I just want to add a space between each character of a string. Can anyone help me figuring out how to do this?
E.g. given "JAYARAM", I need "J A Y A R A M" as the result.
Unless you want to loop through the string and do it "manually" you could solve it like this:
yourString.replace("", " ").trim()
This replaces all "empty substrings" with a space, and then trims off the leading / trailing spaces.
ideone.com demonstration
An alternative solution using regular expressions:
yourString.replaceAll(".(?=.)", "$0 ")
Basically it says "Replace all characters (except the last one) with with the character itself followed by a space".
ideone.com demonstration
Documentation of...
String.replaceAll (including the $0 syntax)
The positive look ahead (i.e., the (?=.) syntax)
StringBuilder result = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
if (i > 0) {
result.append(" ");
}
result.append(input.charAt(i));
}
System.out.println(result.toString());
Iterate over the characters of the String and while storing in a new array/string you can append one space before appending each character.
Something like this :
StringBuilder result = new StringBuilder();
for(int i = 0 ; i < str.length(); i++)
{
result = result.append(str.charAt(i));
if(i == str.length()-1)
break;
result = result.append(' ');
}
return (result.toString());
Blow up your String into array of chars, loop over the char array and create a new string by succeeding a char by a space.
Create a StringBuilder with the string and use one of its insert overloaded method:
StringBuilder sb = new StringBuilder("JAYARAM");
for (int i=1; i<sb.length(); i+=2)
sb.insert(i, ' ');
System.out.println(sb.toString());
The above prints:
J A Y A R A M
This would work for inserting any character any particular position in your String.
public static String insertCharacterForEveryNDistance(int distance, String original, char c){
StringBuilder sb = new StringBuilder();
char[] charArrayOfOriginal = original.toCharArray();
for(int ch = 0 ; ch < charArrayOfOriginal.length ; ch++){
if(ch % distance == 0)
sb.append(c).append(charArrayOfOriginal[ch]);
else
sb.append(charArrayOfOriginal[ch]);
}
return sb.toString();
}
Then call it like this
String result = InsertSpaces.insertCharacterForEveryNDistance(1, "5434567845678965", ' ');
System.out.println(result);
I am creating a java method for this purpose with dynamic character
public String insertSpace(String myString,int indexno,char myChar){
myString=myString.substring(0, indexno)+ myChar+myString.substring(indexno);
System.out.println(myString);
return myString;
}
This is the same problem as joining together an array with commas. This version correctly produces spaces only between characters, and avoids an unnecessary branch within the loop:
String input = "Hello";
StringBuilder result = new StringBuilder();
if (input.length() > 0) {
result.append(input.charAt(0));
for (int i = 1; i < input.length(); i++) {
result.append(" ");
result.append(input.charAt(i));
}
}
public static void main(String[] args) {
String name = "Harendra";
System.out.println(String.valueOf(name).replaceAll(".(?!$)", "$0 "));
System.out.println(String.valueOf(name).replaceAll(".", "$0 "));
}
This gives output as following use any of the above:
H a r e n d r a
H a r e n d r a
One can use streams with java 8:
String input = "JAYARAM";
input.toString().chars()
.mapToObj(c -> (char) c + " ")
.collect(Collectors.joining())
.trim();
// result: J A Y A R A M
A simple way can be to split the string on each character and join the parts using space as the delimiter.
Demo:
public class Main {
public static void main(String[] args) {
String s = "JAYARAM";
s = String.join(" ", s.split(""));
System.out.println(s);
}
}
Output:
J A Y A R A M
ONLINE DEMO
Create a char array from your string
Loop through the array, adding a space +" " after each item in the array(except the last one, maybe)
BOOM...done!!
If you use a stringbuilder, it would be efficient to initalize the length when you create the object. Length is going to be 2*lengthofString-1.
Or creating a char array and converting it back to the string would yield the same result.
Aand when you write some code please be sure that you write a few test cases as well, it will make your solution complete.
I believe what he was looking for was mime code carrier return type code such as %0D%0A (for a Return or line break)
and
\u00A0 (for spacing)
or alternatively
$#032
String handling in Java is something I'm trying to learn to do well. Currently I want to take in a string and replace any characters I find.
Here is my current inefficient (and kinda silly IMO) function. It was written to just work.
public String convertWord(String word)
{
return word.toLowerCase().replace('á', 'a')
.replace('é', 'e')
.replace('í', 'i')
.replace('ú', 'u')
.replace('ý', 'y')
.replace('ð', 'd')
.replace('ó', 'o')
.replace('ö', 'o')
.replaceAll("[-]", "")
.replaceAll("[.]", "")
.replaceAll("[/]", "")
.replaceAll("[æ]", "ae")
.replaceAll("[þ]", "th");
}
I ran 1.000.000 runs of it and it took 8182ms. So how should I proceed in changing this function to make it more efficient?
Solution found:
Converting the function to this
public String convertWord(String word)
{
StringBuilder sb = new StringBuilder();
char[] charArr = word.toLowerCase().toCharArray();
for(int i = 0; i < charArr.length; i++)
{
// Single character case
if(charArr[i] == 'á')
{
sb.append('a');
}
// Char to two characters
else if(charArr[i] == 'þ')
{
sb.append("th");
}
// Remove
else if(charArr[i] == '-')
{
}
// Base case
else
{
sb.append(word.charAt(i));
}
}
return sb.toString();
}
Running this function 1.000.000 times takes 518ms. So I think that is efficient enough. Thanks for the help guys :)
You could create a table of String[] which is Character.MAX_VALUE in length. (Including the mapping to lower case)
As the replacements got more complex, the time to perform them would remain the same.
private static final String[] REPLACEMENT = new String[Character.MAX_VALUE+1];
static {
for(int i=Character.MIN_VALUE;i<=Character.MAX_VALUE;i++)
REPLACEMENT[i] = Character.toString(Character.toLowerCase((char) i));
// substitute
REPLACEMENT['á'] = "a";
// remove
REPLACEMENT['-'] = "";
// expand
REPLACEMENT['æ'] = "ae";
}
public String convertWord(String word) {
StringBuilder sb = new StringBuilder(word.length());
for(int i=0;i<word.length();i++)
sb.append(REPLACEMENT[word.charAt(i)]);
return sb.toString();
}
My suggestion would be:
Convert the String to a char[] array
Run through the array, testing each character one by one (e.g. with a switch statement) and replacing it if needed
Convert the char[] array back to a String
I think this is probably the fastest performance you will get in pure Java.
EDIT: I notice you are doing some changes that change the length of the string. In this case, the same principle applies, however you need to keep two arrays and increment both a source index and a destination index separately. You might also need to resize the destination array if you run out of target space (i.e. reallocate a larger array and arraycopy the existing destination array into it)
My implementation is based on look up table.
public static String convertWord(String str) {
char[] words = str.toCharArray();
char[] find = {'á','é','ú','ý','ð','ó','ö','æ','þ','-','.',
'/'};
String[] replace = {"a","e","u","y","d","o","o","ae","th"};
StringBuilder out = new StringBuilder(str.length());
for (int i = 0; i < words.length; i++) {
boolean matchFailed = true;
for(int w = 0; w < find.length; w++) {
if(words[i] == find[w]) {
if(w < replace.length) {
out.append(replace[w]);
}
matchFailed = false;
break;
}
}
if(matchFailed) out.append(words[i]);
}
return out.toString();
}
My first choice would be to use a StringBuilder because you need to remove some chars from the string.
Second choice would be to iterate throw the array of chars and add the treated char to another array of the inicial size of the string. Then you would need to copy the array to trim the possible unused positions.
After that, I would make some performance tests to see witch one is better.
I doubt, that you can speed up the 'character replacement' at all really. As for the case of regular expression replacement, you may compile the regexs beforehand
Use the function String.replaceAll.
Nice article similar with what you want: link
Any time we have problems like this we use regular expressions are they are by far the fastest way to deal with what you are trying to do.
Have you already tried regular expressions?
What i see being inefficient is that you are gonna check again characters that have already been replaced, which is useless.
I would get the charArray of the String instance, iterate over it, and for each character spam a series of if-else like this:
char[] array = word.toCharArray();
for(int i=0; i<array.length; ++i){
char currentChar = array[i];
if(currentChar.equals('é'))
array[i] = 'e';
else if(currentChar.equals('ö'))
array[i] = 'o';
else if(//...
}
I just implemented this utility class that replaces a char or a group of chars of a String. It is equivalent to bash tr and perl tr///, aka, transliterate. I hope it helps someone!
package your.package.name;
/**
* Utility class that replaces chars of a String, aka, transliterate.
*
* It's equivalent to bash 'tr' and perl 'tr///'.
*
*/
public class ReplaceChars {
public static String replace(String string, String from, String to) {
return new String(replace(string.toCharArray(), from.toCharArray(), to.toCharArray()));
}
public static char[] replace(char[] chars, char[] from, char[] to) {
char[] output = chars.clone();
for (int i = 0; i < output.length; i++) {
for (int j = 0; j < from.length; j++) {
if (output[i] == from[j]) {
output[i] = to[j];
break;
}
}
}
return output;
}
/**
* For tests!
*/
public static void main(String[] args) {
// Example from: https://en.wikipedia.org/wiki/Caesar_cipher
String string = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG";
String from = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String to = "XYZABCDEFGHIJKLMNOPQRSTUVW";
System.out.println();
System.out.println("Cesar cypher: " + string);
System.out.println("Result: " + ReplaceChars.replace(string, from, to));
}
}
This is the output:
Cesar cypher: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
Result: QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD