I read a lot about using StringBuffer and String especially where concatenation is concerned in Java and whether one is thread safe or not.
So, in various Java methods, which should be used?
For example, in a PreparedStatement, should query be a StringBuffer:
String query = ("SELECT * " +
"FROM User " +
"WHERE userName = ?;");
try {
ps = connection.prepareStatement(query);
And then again, in a String utility methods like:
public static String prefixApostrophesWithBackslash(String stringIn) {
String stringOut = stringIn.replaceAll("'", "\\\\'");
return stringOut;
}
And:
// Removes a char from a String.
public static String removeChar(String stringIn, char c) {
String stringOut = ("");
for (int i = 0; i < stringIn.length(); i++) {
if (stringIn.charAt(i) != c) {
stringOut += stringIn.charAt(i);
}
}
return stringOut;
}
Should I be using StringBuffers? Especially where repalceAll is not available for such objects anyway.
Thanks
Mr Morgan.
Thanks for all the advice. StringBuffers have been replaced with StringBuilders and Strings replaced with StringBuilders where I've thought it best.
You almost never need to use StringBuffer.
Instead of StringBuffer you probably mean StringBuilder. A StringBuffer is like a StringBuilder except that it also offers thread safety. This thread safety is rarely needed in practice and will just cause your code to run more slowly.
Your question doesn't seem to be about String vs StringBuffer, but about using built-in methods or implementing the code yourself. If there is a built-in method that does exactly what you want, you should probably use it. The chances are it is much better optimized than the code you would write.
There is no simple answer (apart from repeating the mantra of StringBuilder versus StringBuffer ... ). You really have understand a fair bit about what goes on "under the hood" in order to pick the most efficient solution.
In your first example, String is the way to go. The Java compiler can generate pretty much optimal code (using a StringBuilder if necessary) for any expression consisting of a sequence of String concatenations. And, if the strings that are concatenated are all constants or literals, the compiler can actually do the concatenation at compile time.
In your second example, it is not entirely clear whether String or StringBuilder would be better ... or whether they would be roughly equivalent. One would need to look at the code of the java.util.regex.Matcher class to figure this out.
EDIT - I looked at the code, and actually it makes little difference whether you use a String or StringBuilder as the source. Internally the Matcher.replaceAll method creates a new StringBuilder and fills it by appending chunks from the source String and the replacement String.
In your third example, a StringBuilder would clearly be best. A current generation Java compiler is not able to optimize the code (as written) to avoid creating a new String as each character is added.
For the below segment of code
// Removes a char from a String.
public static String removeChar(String stringIn, char c) {
String stringOut = ("");
for (int i = 0; i < stringIn.length(); i++) {
if (stringIn.charAt(i) != c) {
stringOut += stringIn.charAt(i);
}
}
return stringOut;
}
You could just do stringIn.replaceAll(c+"","")
Even in MT code, it's unusual to have multiple threads append stuff to a string. StringBuilder is almost always preferred to StringBuffer.
Modern compilers optimize the code already. So some String additions will be optimized to use StringBuilder and we can keep the String additions if we think, it increases readibility.
Example 1:
String query = ("SELECT * " +
"FROM User " +
"WHERE userName = ?;");
will be optimized to somthing like:
StringBuiler sb = new StringBuilder();
sb.append("SELECT * ");
sb.append("FROM User ");
sb.append("WHERE userName = ?;");
String query = sb.toString();
Example 2:
String numbers = "";
for (int i = 0;i < 20; i++)
numbers = numbers + i;
This can't be optimized and we should use a StringBuilder in code.
I made this observation for SUN jdk1.5+. So for older Java versions or different jdks it can be different. There it could be save to always code StringBuilder (or StringBuffer for jdk 1.4.2 and older).
For cases which can be considered single threaded, the best would be StringBuilder. It does not add any synchronization overhead, while StringBuffer does.
String concatenation by '+' operator is "good" only when you're lazy to use StringBuilder or just want to keep the code easily readable and it is acceptable from performance point of view, like in startup log message "LOG.info("Starting instance " + inst_id + " of " + app_name);"
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Strings are immutable. Stringbuilders are not, so you can append characters at the end. Strings are character arrays if i am not wrong, than why do we use character arrays separately and Strings separately, Do we really need to use character arrays?
Secondly, there are character arrays and then there are Arraylists. Array lists holds complete objects? I am a bit confused actually.
String cat = "c" + "a" + "t";
cat = cat + cat;
StringBuilder sb = new StringBuilder();
sb.append(city);
sb.append(", ");
sb.append(state);
sb.toString();
Char apple[5]={'a','p','p','l','e'};
Arraylist<MyCar>obj = new Arraylist<MyCar>();
Which should be used where?
This Explain the best: between string and stringBuilder
Ref:Correct way to use StringBuilder
Note that the aim (usually) is to reduce memory churn rather than total memory used, to make life a bit easier on the garbage collector.
Will that take memory equal to using String like below?
No, it'll cause more memory churn than just the straight concat you quoted. (Until/unless the JVM optimizer sees that the explicit StringBuilder in the code is unnecessary and optimizes it out, if it can.)
If the author of that code wants to use StringBuilder (there are arguments for, but also against; see note at the end of this answer), better to do it properly (here I'm assuming there aren't actually quotes around id2 and table):
StringBuilder sb = new StringBuilder(some_appropriate_size);
sb.append("select id1, ");
sb.append(id2);
sb.append(" from ");
sb.append(table);
return sb.toString();
Note that I've listed some_appropriate_size in the StringBuilder constructor, so that it starts out with enough capacity for the full content we're going to append. The default size used if you don't specify one is 16 characters, which is usually too small and results in the StringBuilder having to do reallocations to make itself bigger (IIRC, in the Sun/Oracle JDK, it doubles itself [or more, if it knows it needs more to satisfy a specific append] each time it runs out of room).
You may have heard that string concatenation will use a StringBuilder under the covers if compiled with the Sun/Oracle compiler. This is true, it will use one StringBuilder for the overall expression. But it will use the default constructor, which means in the majority of cases, it will have to do a reallocation. It's easier to read, though. Note that this is not true of a series of concatenations. So for instance, this uses one StringBuilder:
return "prefix " + variable1 + " middle " + variable2 + " end";
It roughly translates to:
StringBuilder tmp = new StringBuilder(); // Using default 16 character size
tmp.append("prefix ");
tmp.append(variable1);
tmp.append(" middle ");
tmp.append(variable2);
tmp.append(" end");
return tmp.toString();
So that's okay, although the default constructor and subsequent reallocation(s) isn't ideal, the odds are it's good enough — and the concatenation is a lot more readable.
But that's only for a single expression. Multiple StringBuilders are used for this:
String s;
s = "prefix ";
s += variable1;
s += " middle ";
s += variable2;
s += " end";
return s;
That ends up becoming something like this:
String s;
StringBuilder tmp;
s = "prefix ";
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable1);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" middle ");
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable2);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" end");
s = tmp.toString();
return s;
...which is pretty ugly.
It's important to remember, though, that in all but a very few cases it doesn't matter and going with readability (which enhances maintainability) is preferred barring a specific performance issue.
Normally String is used for normal string based requirement, and when a String can suffice it.
String Builder is used whenever you want to manipulate and play with the string.
Character Array is used when you want to easily iterate over each and every character
ArrayList is a collection. Use it for holding object of a particular type.
String is immutable object that includes underlying char array.
In your line 2 you discard your String that you created in line 1 and create a new String.
String builder avoids creating new String objects for every separate substring.
Both arrays and Arraylist can contain objects, the main difference is that Arraylist can grow, arrays can not. The second difference is that Arraylist is really a List...
A String uses a char[]. A String is not a char[], in the same way that an ArrayList<String> is not a String[].
ArrayList type is a dynamic data structure. This means that it can grow depending on need. Array is static, meaning it's dimensions do not change over its lifetime.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
when to use StringBuilder in java
If not which of these pieces of code is better and why
public String backAround(String str) {
int len = str.length();
StringBuilder sb = new StringBuilder(str);
char chEnd = sb.charAt(len-1);
if(len > 0){
sb = sb.append(chEnd);
sb= sb.insert(0,chEnd);
str= sb.toString();
return str;
}else{ return str;}
}
or
public String backAround(String str) {
// Get the last char
String back = str.substring(str.length()-1, str.length());
return back + str + back;
}
If you are just "sticking a few elements together" as in your backAround() method, you may as well just use the + notation. The compiler will convert this into appropriate StringBuilder.append()s for you, so why bother 'spelling things out'.
The idea of explicitly using StringBuilder is that in principle you can hand-optimise how exactly the elements are appended to the string, including setting the initial buffer capacity and ensuring that you don't accidentally create intermediate String objects that are unnecessary in cases where the compiler might not predict these things.
So essentially, explicitly use a StringBuilder when there is slightly more complex logic to deciding what to append to the string. For example, if you are appending things in a loop, or where what is appended depends on various conditions at different points. Another case where you might use StringBuilder is if the string needs to be built up from various methods, for example: you can then pass the StringBuilder into the different methods and ask them to append the various elements.
P.S. I should say that StringBuilder buys you a little more editing power as well (e.g. among other things, you can set its length) and, given the presence of the Appendable interface, you can actually create more generic methods that either append to a StringBuilder or to e.g. a StringWriter. But these are marginal cases, I would submit.
It really depends on what you are trying to do. In your case it seems like your trying to take a string and take the last letter and add it to the front and then add another to the end. For this i would probably do this:
public String manipulate(String string)
{
char c = string.charAt(string.length);
return c + string + c;
}
In this case you didn't have to use a StringBuilder. There are cases where the StringBuilder class is useful. Here are some things that are hard to do with a String that StringBuilder can do:
delete chars at an index
append chars at an index
get the index of a specific sequence
and much much more
if you want to see the documentation for StringBuilder:
String Builder
I hope this helped you out!
I have some 'heavy' string manipulation in my Java program, which often involves iterating through a String and replacing certain segments with filler characters, usually "#". These are characters are later removed but are used so that the length of the String and the current index are kept intact during the iteration.
This process usually involves replacing more than 1 character at a time.
e.g.
I might need to replace "cat" with "###" in the string "I love cats", giving "I love ###s",
So often I need to create strings of "#" with x length.
In python, this is easy.
NewString = "#" *x
In Java, I find my current method revolting.
String NewString = "";
for (int i=0; i< x; i++) {
NewString = NewString.concat("#"); }
Is there a proper, pre-established method for doing this?
Does anybody have a shorter, more 'golfed' method?
Thanks!
Specs:
Java SE (Jre7)
Windows 7 (32)
It's not clear to me what kind of regex the comments are suggesting, but creating a string filled with a particular character to the given length is pretty easy:
public static String createString(char character, int length) {
char[] chars = new char[length];
Arrays.fill(chars, character);
return new String(chars);
}
Guava has a nice little method Strings.repeat(String, int). Looking at the source of that method, it basically amounts to this:
StringBuilder builder = new StringBuilder(string.length() * count);
for (int i = 0; i < count; i++) {
builder.append(string);
}
return builder.toString();
Your way of building a string of length N is very inefficient. You should either use StringBuffer with its convenient append method, or build an array of N characters, and use the corresponding constructor of the String.
Can you always use the same characters in the "filler" String and do you know the maximum value of x? The you can create a constant upfront which can be cut to arbitrary length:
private static final FILLER = "##############################################";
// inside your method
String newString = FILLER.substring(0, x);
java.lang.String is immutable. So, concating strings would result in creation of temporary string objects and thus is slow. You should consider using a mutable buffer like StringBuffer or StringBuilder. Another best practice when working with strings in java is to prefer using CharSequence type wherever possible. This would avoid unnecessary calls to toString() and you can easily change the underlying implementation type.
If you are looking for a one liner to repeat strings and this justifies using an external library, have a look at StringUtils.repeat from Apache Commons library. But, I feel you can just write your own code than using another library for a trivial task of repeating strings.
I have code as follows :
String s = "";
for (My my : myList) {
s += my.getX();
}
Findbugs always reports error when I do this.
I would use + if you are manually concatenating,
String word = "Hello";
word += " World!";
However, if you are iterating and concatenating I would suggest StringBuilder,
StringBuilder sb = new StringBuilder();
for (My my : myList) {
sb.append(my.getX());
}
The String object is immutable in Java. Each + means another object. You could use StringBuffer to minimize the amount of created objects.
Each time you do string+=string, it calls method like this:
private String(String s1, String s2) {
if (s1 == null) {
s1 = "null";
}
if (s2 == null) {
s2 = "null";
}
count = s1.count + s2.count;
value = new char[count];
offset = 0;
System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
}
In case of StringBuilder, it comes to:
final void append0(String string) {
if (string == null) {
appendNull();
return;
}
int adding = string.length();
int newSize = count + adding;
if (newSize > value.length) {
enlargeBuffer(newSize);
}
string.getChars(0, adding, value, count);
count = newSize;
}
As you can clearly conclude, string + string creates a lot of overhead, and in my opinion should be avoided if possible. If you think using StringBuilder is bulky or to long you can just make a method and use it indirectly, like:
public static String scat(String... vargs) {
StringBuilder sb = new StringBuilder();
for (String str : vargs)
sb.append(str);
return sb.toString();
}
And use it like:
String abcd = scat("a","b","c","d");
In C# I'm told its about as same as string.Concat();. In your case it would be wise to write overload for scat, like:
public static String scat(Collection<?> vargs) {
StringBuilder sb = new StringBuilder();
for (Object str : vargs)
sb.append(str);
return sb.toString();
}
Then you can call it with:
result = scat(myList)
The compiler can optimize some thing such as
"foo"+"bar"
To
StringBuilder s1=new StringBuilder();
s1.append("foo").append("bar");
However this is still suboptimal since it starts with a default size of 16. As with many things though you should find your biggest bottle necks and work your way down the list. It doesn't hurt to be in the habbit of using a SB pattern from the get go though, especially if you're able to calculate an optimal initialization size.
Premature optimization can be bad as well as it often reduces readability and is usually completely unnecessary. Use + if it is more readable unless you actually have an overriding concern.
It is not 'always bad' to use "+". Using StringBuffer everywhere can make code really bulky.
If someone put a lot of "+" in the middle of an intensive, time-critical loop, I'd be annoyed. If someone put a lot of "+" in a rarely-used piece of code I would not care.
I would say use plus in the following:
String c = "a" + "b"
And use StringBuilder class everywhere else.
As already mentioned in the first case it will be optimized by the compiler and it's more readable.
One of the reasons why FindBugs should argue about using concatenation operator (be it "+" or "+=") is localizability. In the example you gave it is not so apparent, but in case of the following code it is:
String result = "Scanning found " + Integer.toString(numberOfViruses) + " viruses";
If this looks somewhat familiar, you need to change your coding style. The problem is, it will sound great in English, but it could be a nightmare for translators. That's just because you cannot guarantee that order of the sentence will still be the same after translation – some languages will be translated to "1 blah blah", some to "blah blah 3". In such cases you should always use MessageFormat.format() to build compound sentences and using concatenation operator is clearly internationalization bug.
BTW. I put another i18n defect here, could you spot it?
The running time of concatenation of two strings is proportional to the length of the strings. If it is used in a loop running time is always increasing. So if concatenation is needed in a loop its better to use StringBuilder like Anthony suggested.
StringBuffer or HashMap
Which is the best way to append codes and also makes performance better.
StringBuffer sql = new StringBuffer();
DBDatabase db = UTIL.getDatabase();
sql.append("SELECT I.FLDCODE, I.FLDDESCR, I.FLDWORKPHON FROM ");
sql.append(db.getSchema());
sql.append("TRNINSTR I, ");
sql.append(db.getSchema());
sql.append("TRNCRSIN C WHERE C.FLDCOURSE = ? AND C.FLDINSTRUCT = I.FLDCODE AND (I.FLDINACTIVE IS NULL OR I.FLDINACTIVE <> 'y') ORDER BY C.FLDSEQUENCE");
DBPreparedStatement stmt = new DBPreparedStatement(db, sql, "TrainPage.getInfoInstrList");
stmt.setString(1, courseType);
DBResultSet rs = stmt.executeQuery();
stmt.close();
StringBuilder performs even better. Bear in mind that the slow part is database access not statement preparation.
Your question is unclear ("appending codes"? "HashMap"?), but I'll assume that you are asking what is the more efficient way to build a String.
In general, a StringBuilder is more efficient than a StringBuffer, because the latter's methods are synchronized and this is just an unnecessary overhead for a thread-confined object.
But then there is the question of whether using a StringBuilder is more efficient than simple String concatenation. And the answer to that is that "it depends".
If you are doing lots of separate concatenations, then a StringBuilder is typically faster; e.g.
String s = "";
for (int i = 0; i < 1000; i++) {
s += "X";
}
If you are doing all of the concatenations in one expression, then it probably makes no difference:
String s = "Hi " + name + ". It is a might fine " + day + ".";
This is because the Java compiler will turn that into code that creates a StringBuilder and performs a series of append calls.
However, that is a slight over-simplification. On the one hand, if your application can easily calculate the length of the final String, you can get somewhat better performance using a StringBuilder by allocating the builder with the right initial capacity. On the other hand, the compiler will evaluate concatenations of String literals before hand, so
String s = "Hi " + "mom" + ". is a might fine " + "tuesday" + ".";
will be faster than:
StringBuilder sb = new StringBuilder();
sb.append("Hi ");
sb.append("mom");
sb.append(". is a might fine ");
sb.append("tuesday");
sb.append(".");
String s = sb.toString();
But the bottom line is that it probably doesn't matter. Unless you do a huge amount of string building, the chances are that the impact on the overall performance of your application will be minimal.