Related
Let's say there has a string like " world ". This String only has the blank at front and end. Is the trim() faster than replace()?
I used the replace once and my mentor said don't use it since the trim() probably faster.
If not, what's the advantage of trim() than replace()?
If we look at the source code for the methods:
replace():
public String replace(CharSequence target, CharSequence replacement) {
String tgtStr = target.toString();
String replStr = replacement.toString();
int j = indexOf(tgtStr);
if (j < 0) {
return this;
}
int tgtLen = tgtStr.length();
int tgtLen1 = Math.max(tgtLen, 1);
int thisLen = length();
int newLenHint = thisLen - tgtLen + replStr.length();
if (newLenHint < 0) {
throw new OutOfMemoryError();
}
StringBuilder sb = new StringBuilder(newLenHint);
int i = 0;
do {
sb.append(this, i, j).append(replStr);
i = j + tgtLen;
} while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
return sb.append(this, i, thisLen).toString()
}
Vs trim():
public String trim() {
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */
while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}
As you can see replace() calls multiple other methods and iterates throughout the entire String, while trim() simply iterates over the beginning and ending of the String until the character isn't a white space. So in the single respect of trying to only remove white space before and after a word, trim() is more efficient.
We can run some benchmarks on this:
public static void main(String[] args) {
long testStartTime = System.nanoTime();;
trimTest();
long trimTestTime = System.nanoTime() - testStartTime;
testStartTime = System.nanoTime();
replaceTest();
long replaceTime = System.nanoTime() - testStartTime;
System.out.println("Time for trim(): " + trimTestTime);
System.out.println("Time for replace(): " + replaceTime);
}
public static void trimTest() {
for(int i = 0; i < 1000000; i ++) {
new String(" string ").trim();
}
}
public static void replaceTest() {
for(int i = 0; i < 1000000; i ++) {
new String(" string ").replace(" ", "");
}
}
Output:
Time for trim(): 53303903
Time for replace(): 485536597
//432,232,694 difference
Assuming that the people writing the Java library code are doing a good job1, you can assume that a special purpose method (like trim()) will be as fast, and probably faster than a general purpose method (like replace(...)) doing the same thing.
Two reasons:
If the special purpose method is slower, its implementation can be rewritten as equivalent calls to the general purpose one, making the performance equivalent in most cases. A competent programmer will do this because it reduces maintenance costs.
In the special purpose method, it is likely that there will be optimizations that can be made that don't apply in the general-purpose case.
In this case we know that trim() only needs to look at the start and end of the string ... whereas replace(...) needs to look at all of the characters in the string. (We can infer this from the description of what the respective methods do.)
If we assume "competence" then we can infer that the developers will have done the analysis and not implemented trim() sub-optimally2; i.e. they won't code trim() to examine all characters.
There is another reason to use the special purpose method over the general purpose. It makes your code simpler, easier to read, and easier to inspect for correctness. This may well be more important than performance.
This clearly applies in the case of trim() versus replace(...).
1 - We can in this case. There are lots of eyes looking at this code, and lots of people who will complain loudly about egregious performance issues.
2 - Unfortunately, it is not always as straightforward as this. A library method needs to be optimized for "typical" behavior, but it also needs to avoid pathological performance in edge-cases. It is not always possible to achieve both things.
trim() is definitely faster to type, yes. It doesn't take any parameters.
It is also much faster to understand what you where trying to do. You were trying to trim the string, rather than replacing all the spaces it contains with the empty string, knowing from other context that there is only space at the beginning and the end of the string.
Indeed much faster no matter how you look at it. Don't complicate the life of the persons who're trying to read your code. Most of the time, it will be you months later, or at least someone you don't hate.
Trim will prune the outter characters until they are non white space. I believe they trim space, tab, and new lines.
Replace will scan the entire string (so, it could be a sentense) and would replace inner " " with "", essentially compressing them together.
They have different use cases though, obviously 1 is to clean up user input where the other is to update a string where matches are found with something else.
That being said, run times: Replace will run in N time, as it will look for all matching characters. Trim will run in O(N), but most likely a just a few characters off of each end.
The idea behind trim i think came around from people would would type and input things but accidentally press space before submitting their forms, essentially trying to save the field "Foo " instead of "Foo"
s.trim() shortens a String s. This means no characters has to be moved from an index to another. It starts at the first character (s.toCharArray()[0]) of the String and shortens the String character by character until the first non-whitespace character occurs. It works the same way to shorten the String at the end. So it compresses the String. If a String has no leading and trailing whitespace trim will be ready after checking the first and the last character.
In case of " world ".trim() two steps are needed: one to remove the first leading whitespace as it is on the first index and the the second to remove the last whitespace as it is on the last index.
" world ".replace(" ", "") will need at least n = " world ".length() steps. It has to check every character if it has to be replaced. But if we take into account that the implementation of String.replace(...) needs to compile a Pattern, build a Matcher and then to replace all the matched regions it's seems far complex comparing to shorten a String.
We also have to consider that " world ".replace(" ", "") does not replace whitespaces but only the String " ". Since String replace(CharSequence target, CharSequence replacement) compiles the target using Pattern.LITERAL we cannot use the character class \s. To be more accurate we would have to compare " world ".trim() to " world ".replaceAll("\\s", ""). It is still not the same because a whitespace in String trim() is defined as c <= ' ' for each c in s.toCharArray().
Summarizing: String.trim() should be faster - especially for long strings
The description how the methods work is based on the implementation of String in Java 8. But implementations can change.
But the question should be: What do you intent to do with the string? Do you want to trim it or to replace some characters? According to it use the corresponding method.
I'm working on a project where all conversions from int to String are done like this:
int i = 5;
String strI = "" + i;
I'm not familiar with Java.
Is this usual practice or is something wrong, as I suppose?
Normal ways would be Integer.toString(i) or String.valueOf(i).
The concatenation will work, but it is unconventional and could be a bad smell as it suggests the author doesn't know about the two methods above (what else might they not know?).
Java has special support for the + operator when used with strings (see the documentation) which translates the code you posted into:
StringBuilder sb = new StringBuilder();
sb.append("");
sb.append(i);
String strI = sb.toString();
at compile-time. It's slightly less efficient (sb.append() ends up calling Integer.getChars(), which is what Integer.toString() would've done anyway), but it works.
To answer Grodriguez's comment: ** No, the compiler doesn't optimise out the empty string in this case - look:
simon#lucifer:~$ cat TestClass.java
public class TestClass {
public static void main(String[] args) {
int i = 5;
String strI = "" + i;
}
}
simon#lucifer:~$ javac TestClass.java && javap -c TestClass
Compiled from "TestClass.java"
public class TestClass extends java.lang.Object{
public TestClass();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_5
1: istore_1
Initialise the StringBuilder:
2: new #2; //class java/lang/StringBuilder
5: dup
6: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
Append the empty string:
9: ldc #4; //String
11: invokevirtual #5; //Method java/lang/StringBuilder.append:
(Ljava/lang/String;)Ljava/lang/StringBuilder;
Append the integer:
14: iload_1
15: invokevirtual #6; //Method java/lang/StringBuilder.append:
(I)Ljava/lang/StringBuilder;
Extract the final string:
18: invokevirtual #7; //Method java/lang/StringBuilder.toString:
()Ljava/lang/String;
21: astore_2
22: return
}
There's a proposal and ongoing work to change this behaviour, targetted for JDK 9.
It's acceptable, but I've never written anything like that. I'd prefer this:
String strI = Integer.toString(i);
It's not a good way.
When doing conversion from int to string, this should be used:
int i = 5;
String strI = String.valueOf(i);
It's not only the optimization1. I don't like
"" + i
because it does not express what I really want to do 2.
I don't want to append an integer to an (empty) string. I want to convert an integer to string:
Integer.toString(i)
Or, not my prefered, but still better than concatenation, get a string representation of an object (integer):
String.valueOf(i)
1. For code that is called very often, like in loops, optimization sure is also a point for not using concatenation.
2. this is not valid for use of real concatenation like in System.out.println("Index: " + i); or String id = "ID" + i;
A lot of introductory University courses seem to teach this style, for two reasons (in my experience):
It doesn’t require understanding of classes or methods. Usually, this is taught way before the word “class” is ever mentioned – nor even method calls. So using something like String.valueOf(…) would confuse students.
It is an illustration of “operator overloading” – in fact, this was sold to us as the idiomatic overloaded operator (small wonder here, since Java doesn’t allow custom operator overloading).
So it may either be born out of didactic necessity (although I’d argue that this is just bad teaching) or be used to illustrate a principle that’s otherwise quite hard to demonstrate in Java.
The expression
"" + i
leads to string conversion of i at runtime. The overall type of the expression is String. i is first converted to an Integer object (new Integer(i)), then String.valueOf(Object obj) is called. So it is equivalent to
"" + String.valueOf(new Integer(i));
Obviously, this is slightly less performant than just calling String.valueOf(new Integer(i)) which will produce the very same result.
The advantage of ""+i is that typing is easier/faster and some people might think, that it's easier to read. It is not a code smell as it does not indicate any deeper problem.
(Reference: JLS 15.8.1)
Personally, I don't see anything bad in this code.
It's pretty useful when you want to log an int value, and the logger just accepts a string. I would say such a conversion is convenient when you need to call a method accepting a String, but you have an int value.
As for the choice between Integer.toString or String.valueOf, it's all a matter of taste.
...And internally, the String.valueOf calls the Integer.toString method by the way. :)
The other way I am aware of is from the Integer class:
Integer.toString(int n);
Integer.toString(int n, int radix);
A concrete example (though I wouldn't think you need any):
String five = Integer.toString(5); // returns "5"
It also works for other primitive types, for instance Double.toString.
See here for more details.
This technique was taught in an undergraduate level introduction-to-Java class I took over a decade ago. However, I should note that, IIRC, we hadn't yet gotten to the String and Integer class methods.
The technique is simple and quick to type. If all I'm doing is printing something, I'll use it (for example, System.out.println("" + i);. However, I think it's not the best way to do a conversion, as it takes a second of thought to realize what's going on when it's being used this way. Also, if performance is a concern, it seems slower (more below, as well as in other answers).
Personally, I prefer Integer.toString(), as it is obvious what's happening. String.valueOf() would be my second choice, as it seems to be confusing (witness the comments after darioo's answer).
Just for grins :) I wrote up classes to test the three techniques: "" + i, Integer.toString, and String.ValueOf. Each test just converted the ints from 1 to 10000 to Strings. I then ran each through the Linux time command five times. Integer.toString() was slightly faster than String.valueOf() once, they tied three times, and String.valueOf() was faster once; however, the difference was never more than a couple of milliseconds.
The "" + i technique was slower than both on every test except one, when it was 1 millisecond faster than Integer.toString() and 1 millisecond slower than String.valueOf() (obviously on the same test where String.valueOf() was faster than Integer.toString()). While it was usually only a couple milliseconds slower, there was one test where it was about 50 milliseconds slower. YMMV.
There are three ways of converting to Strings
String string = "" + i;
String string = String.valueOf(i);
String string = Integer.toString(i);
There are various ways of converting to Strings:
StringBuilder string = string.append(i).toString();
String string = String.valueOf(i);
String string = Integer.toString(i);
It depends on how you want to use your String. This can help:
String total = Integer.toString(123) + Double.toString(456.789);
Mostly ditto on SimonJ. I really dislike the ""+i idiom. If you say String.valueOf(i), Java converts the integer to a string and returns the result. If you say ""+i, Java creates a StringBuilder object, appends an empty string to it, converts the integer to a string, appends this to the StringBuilder, then converts the StringBuilder to a String. That's a lot of extra steps. I suppose if you do it once in a big program, it's no big deal. But if you're doing this all the time, you're making the computer do a bunch of extra work and creating all these extra objects that then have to be cleaned up. I don't want to get fanatic about micro-optimization, but I don't want to be pointlessly wasteful either.
String strI = String.valueOf(i);
String string = Integer.toString(i);
Both of the ways are correct.
There are many way to convert an integer to a string:
1)
Integer.toString(10);
2)
String hundred = String.valueOf(100); // You can pass an int constant
int ten = 10;
String ten = String.valueOf(ten)
3)
String thousand = "" + 1000; // String concatenation
4)
String million = String.format("%d", 1000000)
Using "" + i is the shortest and simplest way to convert a number to a string. It is not the most efficient, but it is the clearest IMHO and that is usually more important. The simpler the code, the less likely you are to make a mistake.
Personally I think that "" + i does look as the original question poster states "smelly". I have used a lot of OO languages besides Java. If that syntax was intended to be appropriate then Java would just interpret the i alone without needing the "" as desired to be converted to a string and do it since the destination type is unambiguous and only a single value would be being supplied on the right. The other seems like a 'trick" to fool the compiler, bad mojo when different versions of Javac made by other manufacturers or from other platforms are considered if the code ever needs to be ported. Heck for my money it should like many other OOL's just take a Typecast: (String) i. winks
Given my way of learning and for ease of understanding such a construct when reading others code quickly I vote for the Integer.toString(i) method. Forgetting a ns or two in how Java implements things in the background vs. String.valueOf(i) this method feels right to me and says exactly what is happening: I have and Integer and I wish it converted to a String.
A good point made a couple times is perhaps just using StringBuilder up front is a good answer to building Strings mixed of text and ints or other objects since thats what will be used in the background anyways right?
Just my two cents thrown into the already well paid kitty of the answers to the Mans question... smiles
EDIT TO MY OWN ANSWER AFTER SOME REFLECTION:
Ok, Ok, I was thinking on this some more and String.valueOf(i) is also perfectly good as well it says: I want a String that represents the value of an Integer. lol, English is by far more difficult to parse then Java! But, I leave the rest of my answer/comment... I was always taught to use the lowest level of a method/function chain if possible and still maintains readablity so if String.valueOf calls Integer.toString then Why use a whole orange if your just gonna peel it anyways, Hmmm?
To clarify my comment about StringBuilder, I build a lot of strings with combos of mostly literal text and int's and they wind up being long and ugly with calls to the above mentioned routines imbedded between the +'s, so seems to me if those become SB objects anyways and the append method has overloads it might be cleaner to just go ahead and use it... So I guess I am up to 5 cents on this one now, eh? lol...
As already pointed out Integer.toString() or String.valueOf() are the way to go. I was curious and did a quick benchmark:
Integer.toString(i) and String.valueOf(i) are basically identical in performance, with Integer.toString(i) being a tiny bit faster. However i + "" is 1.7 times slower.
import java.util.Random;
public class Test {
public static void main(String[] args) {
long concat = 0;
long valueOf = 0;
long toString = 0;
int iterations = 10000;
int runs = 1000;
for(int i = 0; i < runs; i++) {
concat += concat(iterations);
valueOf += valueOf(iterations);
toString += to_String(iterations);
}
System.out.println("concat: " + concat/runs);
System.out.println("valueOf: " + valueOf/runs);
System.out.println("toString: " + toString/runs);
}
public static long concat(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = r.nextInt() + "";
}
return System.nanoTime() - start;
}
public static long valueOf(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = String.valueOf(r.nextInt());
}
return System.nanoTime() - start;
}
public static long to_String(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = Integer.toString(r.nextInt());
}
return System.nanoTime() - start;
}
}
Output:
concat: 1004109
valueOf: 590978
toString: 587236
use Integer.toString(tmpInt).trim();
Try simple typecasting
char c = (char) i;
The problem I am solving is replacing all Strings from another String.
I solved this problem fairly easily on codingbat.com by using String.replaceAll, and doing it until the first String no longer contains the other String.
However, I dislike this method as it is very slow. I have tried searching this website for more efficient methods, and came across these questions:
Fastest way to perform a lot of strings replace in Java
String.replaceAll is considerably slower than doing the job yourself
They solved the problem by using StringUtils and Patterns. I still think these methods are too slow!
When I code problems like these, I like to get my runtime under two seconds with Java. I'm testing this with a String of 1,000,000 characters. String.replaceAll went well over two seconds, and so did the other two methods.
Does anyone have a fast solution for this problem? Thanks!
EDIT: Unfortunately, the answers I received still run too slowly. And yes, I did mean make a new String, not change the old String, sorry for that mistake.
I'm not sure how it would work, but I think looping over each char and checking might work. Something with algorithms.
Strings are immutable so you can't remove stuff from them. Which means that you need to create a new String without the stuff that you want removed. When you use String.replace that is pretty much what it does: it creates a new String.
Beware of String.replaceAll since it uses a regular expression that gets compiled every time you call it (so never use it in a long loop). This is likely your problem.
If you need to use regular expressions, use the Pattern class to compile your regex and reuse the instance to create a new Matcher for each string you process. If you don't reuse your Pattern instance, it is going to be slow.
If you don't need a regular expression, StringUtils has a replaceEach() that does not rely on regular expressions.
If you are processing a large String. You may want to do things in a streaming fashion and loop over the characters and copy characters over to a StringBuilder.
Alternatively, you could use a regular expression to search for a particular pattern in the String and loop over the matches it finds and for each match append everything from the previous match to the current match to a StringBuilder.
The problem is your String in enormous, you only want to move/copy it once, and all the solutions that use multiple calls to replace will still end up doing an enormous amount of unnecessary work.
What you really want to use is Apache StringUtils.replaceEachRepeatedly, as that method handles searching for multiple strings while only building the result string one.
Apart of the time that each methods (replace, StringUtils or Patterns, ...) takes you only have one Thread working.
If you can split the work done by that thread in two or more, for example each Thread runs for a specific position in the string to other, you will be able to have a fast solution.
The tricky part is to divide the work and then join it together.
That will depend how you read the string, where do you write it in the end for example.
Regards,
I have faced the same problem some time ago and came to this post: Replace all occurrences of a String using StringBuilder?
Using the implementation given in the post:
public static void main(String[] args) {
String from = "A really long string full of ands and ors";
String replaceFrom = "and";
String replaceTo = "or";
long initTime = System.nanoTime();
String result1 = from.replace(replaceFrom, replaceTo);
System.out.println("Time1: " + (System.nanoTime() - initTime));
System.out.println(result1);
StringBuilder sb1 = new StringBuilder(from);
initTime = System.nanoTime();
replaceAll(sb1, replaceFrom, replaceTo);
System.out.println("Time1: " + (System.nanoTime() - initTime));
System.out.println(sb1.toString());
}
// From https://stackoverflow.com/questions/3472663/replace-all-occurences-of-a-string-using-stringbuilder
public static void replaceAll(StringBuilder builder, String from, String to) {
int index = builder.indexOf(from);
while (index != -1) {
builder.replace(index, index + from.length(), to);
index += to.length(); // Move to the end of the replacement
index = builder.indexOf(from, index);
}
}
The explanation of the better performance of the second solution is that it relays on StringBuilder, a mutable object rather than on String an immutable one. See Immutability of Strings in Java for a better explanation.
This solution will work both using StringBuffer and StringBuilder, but as explained in Difference between StringBuilder and StringBuffer StringBuffer is synchronized and StringBuilder is not, so if you don't need synchronisation you better use StringBuilder.
I just tried this, which resulted in :
100960923
197642683484
import java.util.Stack;
public class Test {
public static String removeAll(final String stringToModify, final String stringToFindAndRemove) {
if (stringToModify==null||stringToModify.length()==0) return new String(stringToModify);
if (stringToFindAndRemove==null||stringToFindAndRemove.length()==0) return new String(stringToModify);
if (stringToModify.length()<stringToFindAndRemove.length()) return new String(stringToModify);
int lastChar = 0;
int buffPos=0;
Stack<Integer>stack = new Stack<Integer>();
char[] chars = stringToModify.toCharArray();
char[] ref = stringToFindAndRemove.toCharArray();
char[] ret = new char[chars.length];
for (int a=0;a<chars.length;a++) {
if (chars[a]==ref[buffPos]) {
if (buffPos==ref.length-1) {
buffPos=0;
stack.pop();
} else {
if (buffPos==0) stack.push(lastChar);
buffPos++;
}
} else {
if (buffPos!=0) {
for (int b=0;b<buffPos;b++) {
ret[lastChar]=ref[b];
lastChar++;
}
a--;
buffPos = 0;
} else {
ret[lastChar]=chars[a];
lastChar++;
}
}
if (stack.size()>0&&(lastChar-stack.peek()>=ref.length)) {
while(stack.size()>0 && (lastChar-stack.peek()>=ref.length)) {
int top = stack.pop();
boolean f = true;
for (int foo=0;foo<ref.length;foo++) {
if (ret[top+foo]!=ref[foo]) {
f=false;
break;
}
}
if (f) lastChar=top;
}
}
}
if (buffPos!=0) {
for (int b=0;b<buffPos;b++) {
ret[lastChar]=ref[b];
lastChar++;
}
}
char[] out = new char[lastChar];
System.arraycopy(ret,0,out,0,lastChar);
return new String(out);
}
public static void main(final String[] args) {
StringBuffer s = new StringBuffer();
StringBuffer un = new StringBuffer();
for (int a=0;a<100000;a++) {
s.append("s");
un.append("un");
}
StringBuffer h = new StringBuffer(s);
h.append(un);
h.append("m");
String huge = h.toString();
String t = "sun";
long startTime = System.nanoTime();
String rep = removeAll(huge,t);
long endTime = System.nanoTime();
long duration = (endTime - startTime);
//System.out.println(rep);
System.out.println(duration);
startTime = System.nanoTime();
rep = new String(huge);
int pos = rep.indexOf(t);
while (pos!=-1) {
rep = rep.replaceAll(t,"");
pos = rep.indexOf(t);
}
endTime = System.nanoTime();
duration = (endTime - startTime);
//System.out.println(rep);
System.out.println(duration);
}
}
I'd be interested to see how fast this runs on someone elses machine. Because my boss thinks my machine is fast enough! :)
I'm working on a project where all conversions from int to String are done like this:
int i = 5;
String strI = "" + i;
I'm not familiar with Java.
Is this usual practice or is something wrong, as I suppose?
Normal ways would be Integer.toString(i) or String.valueOf(i).
The concatenation will work, but it is unconventional and could be a bad smell as it suggests the author doesn't know about the two methods above (what else might they not know?).
Java has special support for the + operator when used with strings (see the documentation) which translates the code you posted into:
StringBuilder sb = new StringBuilder();
sb.append("");
sb.append(i);
String strI = sb.toString();
at compile-time. It's slightly less efficient (sb.append() ends up calling Integer.getChars(), which is what Integer.toString() would've done anyway), but it works.
To answer Grodriguez's comment: ** No, the compiler doesn't optimise out the empty string in this case - look:
simon#lucifer:~$ cat TestClass.java
public class TestClass {
public static void main(String[] args) {
int i = 5;
String strI = "" + i;
}
}
simon#lucifer:~$ javac TestClass.java && javap -c TestClass
Compiled from "TestClass.java"
public class TestClass extends java.lang.Object{
public TestClass();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_5
1: istore_1
Initialise the StringBuilder:
2: new #2; //class java/lang/StringBuilder
5: dup
6: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
Append the empty string:
9: ldc #4; //String
11: invokevirtual #5; //Method java/lang/StringBuilder.append:
(Ljava/lang/String;)Ljava/lang/StringBuilder;
Append the integer:
14: iload_1
15: invokevirtual #6; //Method java/lang/StringBuilder.append:
(I)Ljava/lang/StringBuilder;
Extract the final string:
18: invokevirtual #7; //Method java/lang/StringBuilder.toString:
()Ljava/lang/String;
21: astore_2
22: return
}
There's a proposal and ongoing work to change this behaviour, targetted for JDK 9.
It's acceptable, but I've never written anything like that. I'd prefer this:
String strI = Integer.toString(i);
It's not a good way.
When doing conversion from int to string, this should be used:
int i = 5;
String strI = String.valueOf(i);
It's not only the optimization1. I don't like
"" + i
because it does not express what I really want to do 2.
I don't want to append an integer to an (empty) string. I want to convert an integer to string:
Integer.toString(i)
Or, not my prefered, but still better than concatenation, get a string representation of an object (integer):
String.valueOf(i)
1. For code that is called very often, like in loops, optimization sure is also a point for not using concatenation.
2. this is not valid for use of real concatenation like in System.out.println("Index: " + i); or String id = "ID" + i;
A lot of introductory University courses seem to teach this style, for two reasons (in my experience):
It doesn’t require understanding of classes or methods. Usually, this is taught way before the word “class” is ever mentioned – nor even method calls. So using something like String.valueOf(…) would confuse students.
It is an illustration of “operator overloading” – in fact, this was sold to us as the idiomatic overloaded operator (small wonder here, since Java doesn’t allow custom operator overloading).
So it may either be born out of didactic necessity (although I’d argue that this is just bad teaching) or be used to illustrate a principle that’s otherwise quite hard to demonstrate in Java.
The expression
"" + i
leads to string conversion of i at runtime. The overall type of the expression is String. i is first converted to an Integer object (new Integer(i)), then String.valueOf(Object obj) is called. So it is equivalent to
"" + String.valueOf(new Integer(i));
Obviously, this is slightly less performant than just calling String.valueOf(new Integer(i)) which will produce the very same result.
The advantage of ""+i is that typing is easier/faster and some people might think, that it's easier to read. It is not a code smell as it does not indicate any deeper problem.
(Reference: JLS 15.8.1)
Personally, I don't see anything bad in this code.
It's pretty useful when you want to log an int value, and the logger just accepts a string. I would say such a conversion is convenient when you need to call a method accepting a String, but you have an int value.
As for the choice between Integer.toString or String.valueOf, it's all a matter of taste.
...And internally, the String.valueOf calls the Integer.toString method by the way. :)
The other way I am aware of is from the Integer class:
Integer.toString(int n);
Integer.toString(int n, int radix);
A concrete example (though I wouldn't think you need any):
String five = Integer.toString(5); // returns "5"
It also works for other primitive types, for instance Double.toString.
See here for more details.
This technique was taught in an undergraduate level introduction-to-Java class I took over a decade ago. However, I should note that, IIRC, we hadn't yet gotten to the String and Integer class methods.
The technique is simple and quick to type. If all I'm doing is printing something, I'll use it (for example, System.out.println("" + i);. However, I think it's not the best way to do a conversion, as it takes a second of thought to realize what's going on when it's being used this way. Also, if performance is a concern, it seems slower (more below, as well as in other answers).
Personally, I prefer Integer.toString(), as it is obvious what's happening. String.valueOf() would be my second choice, as it seems to be confusing (witness the comments after darioo's answer).
Just for grins :) I wrote up classes to test the three techniques: "" + i, Integer.toString, and String.ValueOf. Each test just converted the ints from 1 to 10000 to Strings. I then ran each through the Linux time command five times. Integer.toString() was slightly faster than String.valueOf() once, they tied three times, and String.valueOf() was faster once; however, the difference was never more than a couple of milliseconds.
The "" + i technique was slower than both on every test except one, when it was 1 millisecond faster than Integer.toString() and 1 millisecond slower than String.valueOf() (obviously on the same test where String.valueOf() was faster than Integer.toString()). While it was usually only a couple milliseconds slower, there was one test where it was about 50 milliseconds slower. YMMV.
There are three ways of converting to Strings
String string = "" + i;
String string = String.valueOf(i);
String string = Integer.toString(i);
There are various ways of converting to Strings:
StringBuilder string = string.append(i).toString();
String string = String.valueOf(i);
String string = Integer.toString(i);
It depends on how you want to use your String. This can help:
String total = Integer.toString(123) + Double.toString(456.789);
Mostly ditto on SimonJ. I really dislike the ""+i idiom. If you say String.valueOf(i), Java converts the integer to a string and returns the result. If you say ""+i, Java creates a StringBuilder object, appends an empty string to it, converts the integer to a string, appends this to the StringBuilder, then converts the StringBuilder to a String. That's a lot of extra steps. I suppose if you do it once in a big program, it's no big deal. But if you're doing this all the time, you're making the computer do a bunch of extra work and creating all these extra objects that then have to be cleaned up. I don't want to get fanatic about micro-optimization, but I don't want to be pointlessly wasteful either.
String strI = String.valueOf(i);
String string = Integer.toString(i);
Both of the ways are correct.
There are many way to convert an integer to a string:
1)
Integer.toString(10);
2)
String hundred = String.valueOf(100); // You can pass an int constant
int ten = 10;
String ten = String.valueOf(ten)
3)
String thousand = "" + 1000; // String concatenation
4)
String million = String.format("%d", 1000000)
Using "" + i is the shortest and simplest way to convert a number to a string. It is not the most efficient, but it is the clearest IMHO and that is usually more important. The simpler the code, the less likely you are to make a mistake.
Personally I think that "" + i does look as the original question poster states "smelly". I have used a lot of OO languages besides Java. If that syntax was intended to be appropriate then Java would just interpret the i alone without needing the "" as desired to be converted to a string and do it since the destination type is unambiguous and only a single value would be being supplied on the right. The other seems like a 'trick" to fool the compiler, bad mojo when different versions of Javac made by other manufacturers or from other platforms are considered if the code ever needs to be ported. Heck for my money it should like many other OOL's just take a Typecast: (String) i. winks
Given my way of learning and for ease of understanding such a construct when reading others code quickly I vote for the Integer.toString(i) method. Forgetting a ns or two in how Java implements things in the background vs. String.valueOf(i) this method feels right to me and says exactly what is happening: I have and Integer and I wish it converted to a String.
A good point made a couple times is perhaps just using StringBuilder up front is a good answer to building Strings mixed of text and ints or other objects since thats what will be used in the background anyways right?
Just my two cents thrown into the already well paid kitty of the answers to the Mans question... smiles
EDIT TO MY OWN ANSWER AFTER SOME REFLECTION:
Ok, Ok, I was thinking on this some more and String.valueOf(i) is also perfectly good as well it says: I want a String that represents the value of an Integer. lol, English is by far more difficult to parse then Java! But, I leave the rest of my answer/comment... I was always taught to use the lowest level of a method/function chain if possible and still maintains readablity so if String.valueOf calls Integer.toString then Why use a whole orange if your just gonna peel it anyways, Hmmm?
To clarify my comment about StringBuilder, I build a lot of strings with combos of mostly literal text and int's and they wind up being long and ugly with calls to the above mentioned routines imbedded between the +'s, so seems to me if those become SB objects anyways and the append method has overloads it might be cleaner to just go ahead and use it... So I guess I am up to 5 cents on this one now, eh? lol...
As already pointed out Integer.toString() or String.valueOf() are the way to go. I was curious and did a quick benchmark:
Integer.toString(i) and String.valueOf(i) are basically identical in performance, with Integer.toString(i) being a tiny bit faster. However i + "" is 1.7 times slower.
import java.util.Random;
public class Test {
public static void main(String[] args) {
long concat = 0;
long valueOf = 0;
long toString = 0;
int iterations = 10000;
int runs = 1000;
for(int i = 0; i < runs; i++) {
concat += concat(iterations);
valueOf += valueOf(iterations);
toString += to_String(iterations);
}
System.out.println("concat: " + concat/runs);
System.out.println("valueOf: " + valueOf/runs);
System.out.println("toString: " + toString/runs);
}
public static long concat(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = r.nextInt() + "";
}
return System.nanoTime() - start;
}
public static long valueOf(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = String.valueOf(r.nextInt());
}
return System.nanoTime() - start;
}
public static long to_String(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = Integer.toString(r.nextInt());
}
return System.nanoTime() - start;
}
}
Output:
concat: 1004109
valueOf: 590978
toString: 587236
use Integer.toString(tmpInt).trim();
Try simple typecasting
char c = (char) i;
What method of capitalizing is better?
mine:
char[] charArray = string.toCharArray();
charArray[0] = Character.toUpperCase(charArray[0]);
return new String(charArray);
or
commons lang - StringUtils.capitalize:
return new StringBuffer(strLen)
.append(Character.toTitleCase(str.charAt(0)))
.append(str.substring(1))
.toString();
I think mine is better, but i would rather ask.
I guess your version will be a little bit more performant, since it does not allocate as many temporary String objects.
I'd go for this (assuming the string is not empty):
StringBuilder strBuilder = new StringBuilder(string);
strBuilder.setCharAt(0, Character.toUpperCase(strBuilder.charAt(0))));
return strBuilder.toString();
However, note that they are not equivalent in that one uses toUpperCase() and the other uses toTitleCase().
From a forum post:
Titlecase <> uppercase
Unicode
defines three kinds of case mapping:
lowercase, uppercase, and titlecase.
The difference between uppercasing and
titlecasing a character or character
sequence can be seen in compound
characters (that is, a single
character that represents a compount
of two characters).
For example, in Unicode, character
U+01F3 is LATIN SMALL LETTER DZ. (Let
us write this compound character
using ASCII as "dz".) This character
uppercases to character U+01F1, LATIN
CAPITAL LETTER DZ. (Which is
basically "DZ".) But it titlecases to
to character U+01F2, LATIN CAPITAL
LETTER D WITH SMALL LETTER Z. (Which
we can write "Dz".)
character uppercase titlecase
--------- --------- ---------
dz DZ Dz
If I were to write a library, I'd try to make sure I got my Unicode right beofre worrying about performance. Off the top of my head:
int len = str.length();
if (len == 0) {
return str;
}
int head = Character.toUpperCase(str.codePointAt(0));
String tail = str.substring(str.offsetByCodePoints(0, 1));
return new String(new int[] { head }).concat(tail);
(I'd probably also look up the difference between title and upper case before I committed.)
Performance is equal.
Your code copies the char[] calling string.toCharArray() and new String(charArray).
The apache code on buffer.append(str.substring(1)) and buffer.toString(). The apache code has an extra string instance that has the base char[1,length] content. But this will not be copied when the instance String is created.
StringBuffer is declared to be thread safe, so it might be less effective to use it (but one shouldn't bet on it before actually doing some practical tests).
StringBuilder (from Java 5 onwards) is faster than StringBuffer if you don't need it to be thread safe but as others have said you need to test if this is better than your solution in your case.
Have you timed both?
Honestly, they're equivalent.. so the one that performs better for you is the better one :)
Not sure what the difference between toUpperCase and toTitleCase is, but it looks as if your solution requires one less instantiation of the String class, while the commons lang implementation requires two (substring and toString create new Strings I assume, since String is immutable).
Whether that's "better" (I guess you mean faster) I don't know. Why don't you profile both solutions?
look at this question titlecase-conversion . apache FTW.
/**
* capitalize the first letter of a string
*
* #param String
* #return String
* */
public static String capitalizeFirst(String s) {
if (s == null || s.length() == 0) {
return "";
}
char first = s.charAt(0);
if (Character.isUpperCase(first)) {
return s;
} else {
return Character.toUpperCase(first) + s.substring(1);
}
}
If you only capitalize limited words, you better cache it.
#Test
public void testCase()
{
String all = "At its base, a shell is simply a macro processor that executes commands. The term macro processor means functionality where text and symbols are expanded to create larger expressions.\n" +
"\n" +
"A Unix shell is both a command interpreter and a programming language. As a command interpreter, the shell provides the user interface to the rich set of GNU utilities. The programming language features allow these utilities to be combined. Files containing commands can be created, and become commands themselves. These new commands have the same status as system commands in directories such as /bin, allowing users or groups to establish custom environments to automate their common tasks.\n" +
"\n" +
"Shells may be used interactively or non-interactively. In interactive mode, they accept input typed from the keyboard. When executing non-interactively, shells execute commands read from a file.\n" +
"\n" +
"A shell allows execution of GNU commands, both synchronously and asynchronously. The shell waits for synchronous commands to complete before accepting more input; asynchronous commands continue to execute in parallel with the shell while it reads and executes additional commands. The redirection constructs permit fine-grained control of the input and output of those commands. Moreover, the shell allows control over the contents of commands’ environments.\n" +
"\n" +
"Shells also provide a small set of built-in commands (builtins) implementing functionality impossible or inconvenient to obtain via separate utilities. For example, cd, break, continue, and exec cannot be implemented outside of the shell because they directly manipulate the shell itself. The history, getopts, kill, or pwd builtins, among others, could be implemented in separate utilities, but they are more convenient to use as builtin commands. All of the shell builtins are described in subsequent sections.\n" +
"\n" +
"While executing commands is essential, most of the power (and complexity) of shells is due to their embedded programming languages. Like any high-level language, the shell provides variables, flow control constructs, quoting, and functions.\n" +
"\n" +
"Shells offer features geared specifically for interactive use rather than to augment the programming language. These interactive features include job control, command line editing, command history and aliases. Each of these features is described in this manual.";
String[] split = all.split("[\\W]");
// 10000000
// upper Used 606
// hash Used 114
// 100000000
// upper Used 5765
// hash Used 1101
HashMap<String, String> cache = Maps.newHashMap();
long start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++)
{
String upper = split[i % split.length].toUpperCase();
// String s = split[i % split.length];
// String upper = cache.get(s);
// if (upper == null)
// {
// cache.put(s, upper = s.toUpperCase());
//
// }
}
System.out.println("Used " + (System.currentTimeMillis() - start));
}
The text is picked from here.
Currently, I need to upper case the table name and columns, many many more times, but they are limited.Use the hashMap to cache will be better.
:-)
use this method for capitalizing of string. its totally working without any bug
public String capitalizeString(String value)
{
String string = value;
String capitalizedString = "";
System.out.println(string);
for(int i = 0; i < string.length(); i++)
{
char ch = string.charAt(i);
if(i == 0 || string.charAt(i-1)==' ')
ch = Character.toUpperCase(ch);
capitalizedString += ch;
}
return capitalizedString;
}