This question already has answers here:
How to insert a character in a string at a certain position?
(14 answers)
Closed 7 years ago.
I'm trying to use StringBuffer#insert to insert a char into different positions in a word but either I'm not using it right or I've misunderstood what it is this function actually does.
First off, I want it to add the letter 't' into different positions within "Java". I've given the part of the code I'm trying to use.
For example, the first time it's run it should print "tJava", then second time "Jtava" and so on until the loop ends after it prints "Javat". However, all I'm getting is:
tJava
ttJava
tttJava
ttttJava
If I'm using it wrong or there is an alternative way of doing this suggestions would be greatly appreciated.
String addLetter = "t";
String Word = "Java";
StringBuffer tempWord = new StringBuffer(Word);
for(int i = 0; i<Word.length(); i++) {
tempWord = tempWord.insert(i, addLetter);
System.out.println(tempWord);
}
When you call insert on StringBuffer the inserted value will be kept. For example :
StringBuffer test = new StringBuffer("test");
test.insert(1, "t");
test.insert(3, "t");
System.out.println(test);
would print ttetst.
So your re-assignment is not needed tempWord = tempWord.insert(i, "t"); if really you would want to keep the updated string.
Now if you want to display the original string with only 1 added character at the correct position, you will have to re-assign word to tempWord at each iteration.
String addLetter = "t";
String Word = "Java";
StringBuffer tempWord = new StringBuffer(Word);
for(int i = 0; i<Word.length(); i++) {
tempWord = new StringBuffer(Word);
System.out.println(tempWord.insert(i, addLetter));
}
StringBuffer and StringBuilder classes are mutable. You use a single reference and keep inserting data in it, thus you get this result.
Move the declaration and initialization of the StringBuffer inside the loop.
//removed (commented)
//StringBuffer tempWord = new StringBuffer(Word);
for(int i = 0; i<Word.length(); i++) {
//using StringBuilder rather than StringBuffer since you don't need synchronization at all
StringBuilder tempWord = new StringBuilder(Word);
tempWord = tempWord.insert(i, addLetter);
System.out.println(tempWord);
}
Let's look at the iterations:
i goes from 0 to "Java".length() = 4
i = 0 -> insert t in 0 -> Java -> t + Java
i = 1 -> insert t in 1 -> tJava -> t + t + Java
i = 2 -> insert t in 2 -> ttJava -> tt + t + Java
i = 3 -> insert t in 3 -> tttJava -> ttt + t + Java
What you want is in insert t in Java at a different index at each iteration, not at the result of the previous iteration.
Therefore you should not use the result of the previous iteration but re-assign your buffer:
for(int i = 0 ; i < word.length() ; i++) {
StringBuilder sb = new StringBuilder(word);
System.out.println(sb.insert(i, "t"));
}
If you insist on using a StringBuffer, you should reassign it to the original word for each iteration. The buffer remembers the insertion.
String addLetter = "t";
String word = "Java";
for(int i = 0; i<Word.length(); i++) {
StringBuffer tempWord = new StringBuffer(word);
tempWord.insert(i, addLetter);
System.out.println(tempWord);
}
Otherwise see Insert a character in a string at a certain position
StringBuilder is mutable and will update itself on the call to insert, and thus every loop iteration the instance is updated. To insert the value into the ORIGINAL string at each loop iteration, you should create a new object set to the original String
for(int i = 0; i<Word.length(); i++)
{
StringBuffer tempWord = new StringBuffer(Word);
System.out.println(tempWord.insert(i, addLetter));
}
Related
I'm trying to join an array of Strings using the String.join() method. I need the first item of the array to be removed (or set to empty). If I have a string array such as {"a","b","c","d"}, I want to return only b.c.d.
If it can be done with a for loop, that is fine. I currently have:
for (int i=1; i<item.length; i++) {
newString += item[i] + ".";
}
Try using Arrays.copyOfRange to skip the first element of the array:
String.join(".", Arrays.copyOfRange(item, 1, item.length));
Demo
You can do it as follows:
String.join(".", Arrays.stream(myArray, 1, myArray.length).collect(Collectors.toList()));
or if you want the . suffix in the result then use joining collector:
Arrays.stream(myArray, 1, myArray.length)
.collect(Collectors.joining(".","","."));
An alternative with streams:
String result = Arrays.stream(item)
.skip(1)
.collect(joining("."));
Or this can also be a possible answer
String.join(".",myarray).substring(myarray[0].length()+1);
try this
String[] a = new String[] {"a","b","c","d"};
String newString = "";
for (int i=1; i<a.length; i++) {
if (i > 0) {
newString += a[i] + ".";
}
}
System.out.println(newString);
try using following code
public static String getJoined(String []strings) {
StringBuilder sbr = new StringBuilder(); // to store joined string
// skip first string, iterate over rest of the strings.
for(int i=1; i<strings.length; i++) {
// append current string and '.'
sbr.append(strings[i]).append(".");
}
// remove last '.' , it will not be required.
// if not deleted the result will be contain '.' at end.
// e.g for {"a","b","c"} the result will be "b.c." instead of "b.c"
sbr.delete(sbr.length()-1, sbr.length());
return sbr.toString();
}
I'm having performance issues. Does anyone have a faster/better solution for doing the following:
String main = "";
for (String proposition : propositions) {
if (main.length() == 0) {
main = proposition;
} else {
main = "|(" + proposition + "," + main + ")";
}
}
I know concat and stringbuilder are faster, but i don't see how i can use these methods. Because of the following line of code:
main = "|(" + proposition + "," + main + ")";
Thanks in advance!
So from what I can tell there are 3 problems here:
Values are primarily prepended to the string.
For each value a character is appended.
If only one value is present, nothing should be appended or prepended.
With 2 or more items, the 0th item is handled differently:
0:""
1:"A"
2:"|(B,A)"
3:"|(C,|(B,A))"
It can be made quicker by making a few changes:
Reverse the algorithm, this means the majority of the work involves appending, allowing you to use StringBuilders.
Count the number of closing )'s and append those after the loop is finished.
Special case for 0 or 1 items in the list.
With those changes the algorithm should be able to use a StringBuilder and be a lot quicker.
Attempt at an algorithm:
int length = propositions.size();
if (length == 0) {
main = "";
} else {
StringBuilder sb = new StringBuilder();
int nestingDepth = 0;
// Reverse loop, ignoring 0th element due to special case
for (int i = length - 1; i > 0; i--) {
sb.append("|(").append(propositions.get(i)).append(',');
nestingDepth++;
}
// Append last element due to special casing
sb.append(propositions.get(0));
for (int i = 0; i < nestingDepth; i++) {
sb.append(')');
}
main = sb.toString();
}
I believe this should produce the correct results, but it should give the right idea.
The problem is that you're prepending and appending to the string as you go. String and StringBuilder dont handle this well (and give quadratic performance). But you can use a dequeue which supports insertion at start and end to store all the pieces. Then finally you can join the bits in the dequeue.
ArrayDeque bits = new ArrayDeque();
for (String proposition : propositions) {
if (bits.size() == 0) {
bits.push(proposition);
} else {
// Add prefix
main.offerFirst("|(" + proposition + "," );
// Add suffix
main.push(")");
}
}
StringBuilder sb = new StringBuilder();
for( String s : bits) {
sb.append(s);
}
main = sb.toString();
Assuming this is an array of propositions, you could first sum the length of the String(s) in the array. Add 4 for your additional characters, and subtract 4 because you don't use those separators on the first element. That should be the perfect size for your output (this is optional, because StringBuilder is dynamically sized). Next, construct a StringBuilder. Add the first element. All subsequent elements follow the same pattern, so the loop is simplified with a traditional for. Something like,
int len = Stream.of(propositions).mapToInt(s -> s.length() + 4).sum() - 4;
StringBuilder sb = new StringBuilder(len); // <-- len is optional
sb.append(propositions[0]);
for (int i = 1; i < propositions.length; i++) {
sb.insert(0, ",").insert(0, propositions[i]).insert(0, "|(").append(")");
}
System.out.println(sb);
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);
This question already has answers here:
How to convert an int array to String with toString method in Java [duplicate]
(8 answers)
Closed 9 years ago.
I am trying to take an arbitrary-length String[] and print it out to a String, preferably with field separators. Right now I have:
String[] start = {"first", "second", "third"}; //[] to convert
String cC = "";
String finish = ""; // Final String
String cC1 = "";
{
for (int i = 0; i < puts.length; i++) {
cC = puts[i] + ", ";
cC1 = (finish + cC);
finish = cC1;
}
}
But for some reason it is only returning the "second" value. How can I make it properly concatenate the values?
Also, could I simplify the code by using finish += cC? Thanks.
String[] start = {"first", "second", "third"};
String addedTogether = Arrays.toString(start);
System.out.println(addedTogether);
//prints [first, second, third]
If You want to append to a string you should use +=
e.g.
String[] start = {"first", "second", "third"};
String cc = "";
String separator = ",";
for (int i = 0; i < start.length; i++) {
cc += start[i];
//Not Add , if it is the last element.
if(i!=start.length-1){
cc+=separator;
}
}
etc.
with your way you are setting the last value to finish.
String[] start = {"first", "second", "third"}; //[] to convert
String finish = ""; // Final String
{
for (int i = 0; i < starts.length; i++) {
finish = finish + start[i] + ", ";
}
}
(If you wanted to do all this manually for some reason...)
Check out -- Java equivalents of C# String.Format() and String.Join()
That provides a string.join method, as well as some reading on useful string utility methods.
It is a very bad idea to concatenate Strings using += operator. It is always better to construct StringBuilder object and append all the values to it. And lastly call toString() on the StringBuilder object.
Take a look at this link to understand the performance hit associated with using + operator for string concatenation.
http://blog.eyallupu.com/2010/09/under-hood-of-java-strings.html
How Java do the string concatenation using "+"?
Hi all I wrote a mergesort program for a string array that reads in .txt files from the user. But what I want to do now is compare both files and print out the words in file one and not in file two for example apple is in file 1 but not file 2. I tried storing it in a string array again and then printing that out at the end but I just cant seem to implement it.
Here is what I have,
FileIO reader = new FileIO();
String words[] = reader.load("C:\\list1.txt");
String list[] = reader.load("C:\\list2.txt");
mergeSort(words);
mergeSort(list);
String x = null ;
for(int i = 0; i<words.length; i++)
{
for(int j = 0; j<list.length; j++)
{
if(!words[i].equals(list[j]))
{
x = words[i];
}
}
}
System.out.println(x);
Any help or suggestions would be appriciated!
If you want to check the words that are in the first array but do not exist in the second, you can do like this:
boolean notEqual = true;
for(int i = 0; i<words.length; i++)
{
for(int j = 0; j<list.length && notEqual; j++)
{
if(words[i].equals(list[j])) // If the word of file one exist
{ // file two we set notEqual to false
notEqual = false; // and we terminate the inner cycle
}
}
if(notEqual) // If the notEqual remained true
System.out.println(words[i]); // we print the the element of file one
// that do not exist in the second file
notEqual = true; // set variable to true to be used check
} // the other words of file one.
Basically, you take a word from the first file (string from the array) and check if there is a word in file two that is equal. If you find it, you set the control variable notEqual to false, thus getting out of the inner loop for and not print the word. Otherwise, if there is not any word on file two that match the word from file one, the control variable notEqual will be true. Hence, print the element outside the inner loop for.
You can replace the printing statement, for another one that store the unique word in an extra array, if you wish.
Another solution, although slower that the first one:
List <String> file1Words = Arrays.asList(words);
List <String> file2Words = Arrays.asList(list);
for(String s : file1Words)
if(!file2Words.contains(s))
System.out.println(s);
You convert your arrays to a List using the method Arrays.asList, and use the method contains to verify if the word of the first file is on the second file.
Why not just convert the Arrays to Sets? Then you can simply do
result = wordsSet.removeAll(listSet);
your result will contain all the words that do not exist in list2.txt
Also keep in mind that the set will remove duplicates ;)
you can also just go through the loop and add it when you reached list.length-1.
and if it matches you can break the whole stuff
FileIO reader = new FileIO();
String words[] = reader.load("C:\\list1.txt");
String list[] = reader.load("C:\\list2.txt");
mergeSort(words);
mergeSort(list);
//never ever null
String x = "" ;
for(int i = 0; i<words.length; i++)
{
for(int j = 0; j<list.length; j++)
{
if(words[i].equals(list[j]))
break;
if(j == list.length-1)
x += words[i] + " ";
}
}
System.out.println(x);
Here is a version (though it does not use sorting)
String[] file1 = {"word1", "word2", "word3", "word4"};
String[] file2 = {"word2", "word3"};
List<String> l1 = new ArrayList(Arrays.asList(file1));
List<String> l2 = Arrays.asList(file2);
l1.removeAll(l2);
System.out.println("Not in file2 " + l1);
it prints
Not in file2 [word1, word4]
This looks kind of close. What you're doing is for every string in words, you're comparing it to every word in list, so if you have even one string in list that's not in words, x is getting set.
What I'd suggest is changing if(!words[i].equals(list[j])) to if(words[i].equals(list[j])). So now you know that the string in words appears in list, so you don't need to display it. if you completely cycle through list without seeing the word, then you know you need to explain it. So something like this:
for(int i = 0; i<words.length; i++)
{
boolean wordFoundInList = false;
for(int j = 0; j<list.length; j++)
{
if(words[i].equals(list[j]))
{
wordFoundInList = true;
break;
}
}
if (!wordFoundInList) {
System.out.println(x);
}
}