I can use either concatenation operator(+) or concat() method for string concatenation
String myData = "a"+"b"; // using concatenation operator
String myData = "a".concat("b"); // using concat() of String
But to concate a string with integer I cannot use concat() directly. SO I have to use either of the following logic
String myData = "a"+5;
String myData = "a".concat(String.valueOf(5));
But I found some thing strange in the following line when I want to use concatenation operator and concat
String myData = "a"+null; //output = anull
String myData = "a".concat(String.valueOf(5)); // output = NullPointerException
or
String myData = "a".concat(null); // output = NullPointerException
I have below question arised in my mind
1) How concat() method and concatenation operator works what is the difference in their logic of performing any task?
2) Can we really concat a null using (+) if so why concat() method cannot achieve the same
Thanks
1) The + operator (to produce Strings) always goes through an intermediate StringBuilder (or StringBuffer if targeting old platforms before 1.5 (released 7 (seven) years ago)). For concatenating two or perhaps three Strings concat will generally be faster due to the lack of intermediate. However, for longer concatenations + will win because there will be fewer intermediate allocations.
2) null generally indicates an error (quite possibly a design error). In general, errors should be reported as early as possible, which String.concat does. However, + or StringBuilder concatenation is often used to produce debug strings, so the null is tolerated and produces a result suitable for debugging (but not UI!).
There's no difference in the semantics, you just got your example wrong.
String myData = "a"+null; //output = anull
String myData = "a".concat(String.valueOf( (Object)null ) ); // output = anull
And this will compile and work. + behaves as if String.valueOf() was invoked for every operand.
Related
This question already has answers here:
StringBuilder vs String concatenation in toString() in Java
(20 answers)
Closed 7 years ago.
I am concatenating a String in a loop but it takes ages, why is that?
for (String object : jsonData) {
counter++;
finalJsonDataStr += object;
}
Variable object is a piece of JSON, up to 70 chars and the loop goes approx 50k times.
I understand some people advice StringBuffer or StringBuilder but this link says, it has no performance improvements: StringBuilder vs String concatenation in toString() in Java
Use a String Builder to append to strings.
When you concatenate, Java is actually creating a new String with the results of the concatenation.
Do it multiple times and you are creating gazillion of strings for nothing.
Try:
StringBuilder sb = new StringBuilder();
for (String object : jsonData) {
counter++;
sb.append(object.toString()); //this does the concatenation internally
//but is very efficient
}
finalJsonDataStr = sb.toString(); //this gives you back the whole string
Remark:
When you do stuff like
myString = "hello " + someStringVariable + " World!" + " My name is " + name;
The compiler is smart enough to replace all that with a single StringBuilder, like:
myString = new StringBuilder("hello ")
.append(someStringVariable)
.append(" World!")
.append(" My name is ")
.append(name).toString();
But for some reason I don't know, it doesn't do it when the concatenation happens inside a loop.
You should use a StringBuffer or a StringBuilder.
When you add Strings with plus, a StringBuilder is created, strings are concatenated and a new String is return with toString() method of the StringBuilder. So image this object creation and string manipulation 50k times. It's much better if you instantiate only one StringBuilder yourself and just append strings...
This answer could be of use to you: concatenation operator (+) vs concat()
Before going to the actual problem, see how internal concatenation works.
String testString ="str"+"ingcon"+"catenation";
If we print the above declared String to console and see, the result is stringconcatenation.Which is correct and the + works fine. Here is out actual question, how does that + symbol did the magic ? ? Is it not a normal mathematical addition of Strings. The below code snippet shows how that code with + actually converts.
StringBuilder compilerGeneratedBuilder = new StringBuilder();
compilerGeneratedBuilder.append("str");
compilerGeneratedBuilder.append("ingcon");
compilerGeneratedBuilder.append("catenation");
String finalString = compilerGeneratedBuilder.toString();
More .....
50K times loop is a descent performance blocker to consider.
In such cases use StringBuilder with append method. Cause concat (+) create a new object every time a new String Builder object. That leads to 50k objects creations.
With single StringBuilder and append method, you can save the time of Objection creation as well as the memory too.
This question already has answers here:
StringBuilder vs String concatenation in toString() in Java
(20 answers)
Closed 6 years ago.
What is the benefit and trade-off of using a string builder over pure string concatenation?
new StringBuilder(32).append(str1)
.append(" test: ")
.append(val)
.append(" is changed")
.toString();
vs say
str1 + " test: " + val + " is changed".
str1 is a random 10 character string.
str2 is a random 8 character string.
In your particular example, none because the compiler internally uses StringBuilders to do String concatenation. If the concatenation occurred in a loop, however, the compiler could create several StringBuilder and String objects. For example:
String s= "" ;
for(int i= 0 ; i < 10 ; i++ )
s+= "a" ;
Each time line 3 above is executed, a new StringBuilder object is created, the contents of s appended, "a" appended, and then the StringBuilder is converted into a String to be assigned back to s. A total of 10 StringBuilders and 10 Strings.
Conversely, in
StringBuilder sb= new StringBuilder() ;
for(int i= 0 ; i < 10 ; i++ )
sb.append( "a" );
String s= sb.toString() ;
Only 1 StringBuilder and 1 String are created.
The main reason for this is that the compiler could not be smart enough to understand that the first loop is equivalent to the second and generate more efficient (byte) code. In more complex cases, it's impossible even for the smartest compiler to know. If you absolutely need this optimization, you have to introduce it manually by using StringBuilders explicitly.
The quick answer is the performance:
when you are using native String classes it operates immutable strings, which means when you are writing
String line = "java";
String sufix = " is awesome";
line = line + sufix;
it will create two strings "java" and " is awesome", than create a new third string "java is awesome" from previous two ("java" and "is awesome") which later are likely to be deleted by a garbage collector (because they are no more used in app). That is a slow solution.
More faster solution is an appliance of StringBuffer class which through the smart algorightms that provide a buffer (that is obvious from its name) for merging strings and as a result would not remove the initial string during the concatenation process.
In case you are writing single thread-application (no concurrancy issues during which multiple threads access same object) it is better to apply StringBuilder which has even faster performance than the initial StringBuffer class.
I'm having a minor issue with Java String comparisons.
I've written a class which takes in a String and parses it into a custom tree type. I've written a toString class which then converts this tree back to a String again. As part of my unit tests I'm just checking that the String generated by the toString method is the same as the String that was parsed in the first place.
Here is my simple test with a few printouts so that we can see whats going on.
final String exp1 = "(a|b)";
final String exp2 = "((a|b)|c)";
final Node tree1 = Reader.parseExpression2(exp1);
final Node tree2 = Reader.parseExpression2(exp2);
final String t1 = tree1.toString();
final String t2 = tree2.toString();
System.out.println(":" + exp1 + ":" + t1 + ":");
System.out.println(":" + exp2 + ":" + t2 + ":");
System.out.println(exp1.compareToIgnoreCase(t1));
System.out.println(exp2.compareToIgnoreCase(t2));
System.out.println(exp1.equals(t1));
System.out.println(exp2.equals(t2));
Has the following output; (NB ":" - are used as delineators so I can ensure theres no extra whitespace)
:(a|b):(a|b):
:((a|b)|c):((a|b)|c):
-1
-1
false
false
Based on manually comparing the strings exp1 and exp2 to t1 and t2 respectively, they are exactly the same. But for some reason Java is insisting they are different.
This isn't the obvious mistake of using == instead of .equals() but I'm stumped as to why two seemingly identical strings are different. Any help would be much appreciated :)
Does one of your strings have a null character within it? These might not be visible when you use System.out.println(...).
For example, consider this class:
public class StringComparison {
public static void main(String[] args) {
String s = "a|b";
String t = "a|b\0";
System.out.println(":" + s + ":" + t + ":");
System.out.println(s.equals(t));
}
}
When I ran this on Linux it gave me the following output:
:a|b:a|b:
false
(I also ran it on Windows, but the null character showed up as a space.)
Well, it certainly looks okay. What I would do would be to iterate over both strings using charAt to compare every single character with the equivalent in the other string. This will, at a minimum, hopefully tell you the offending character.
Also output everything else you can find out about both strings, such as the length.
It could be that one of the characters, while looking the same, may be some other Unicode doppelganger :-)
You may also want to capture that output and do a detailed binary dump on it, such as loading it up into gvim and using the hex conversion tool, or executing od -xcb (if available) on the captured output. There may be an obvious difference when you get down to the binary examination level.
I have some suggestions
Copy each output and paste in Notepad (or any similar editor), then
copy them again and do something like this
System.out.println("(a|b)".compareToIgnoreCase("(a|b)"));
Print out the integer representation of each character. If it is a weird unicode, the int representation will be different.
Also what version of JDK are you using?
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why to use StringBuffer in Java instead of the string concatenation operator
what is the advantage or aim of doing this
int a= 42
StringBuffer sb = new StringBuffer(40);
String s = sb.append("a = ").append(a).append("!").toString();
System.out.println(sb);
result > a = 42!
instead of
int a= 42
String s = "a = " + a + "!";
System.out.println(sb);
In your scenario, I'm not sure there is a difference b/c all of your "+" are on one line (which only creates a String once). In general, though, Strings are immutable objects and are not truly manipulated but rather created and discarded using StringBuffers.
So ultimately, you will have more efficient code if you use StringBuffers (and generally StringBuilders). If you google "String vs. StringBuffer vs. StringBuilder" you can find many articles detailing the statistics.
Efficiency. String concatenation in Java uses StringBuilders in the background anyway, so in some cases you can eke out a bit of efficiency by controlling that yourself.
Just run the code for 10000 time and measure the time. It should be obvious.
Some background-information: String is immutable while StringBuilder is not. So everytime you concatenate a String you have to copy an array.
PS: Sometimes the compiler optimizes things though. Maybe if you make your variable static final it would be just one String internally and no concatenation.
First of all, StringBuffer is synchronized, so you would typically use StringBuilder. + has been reimplemented to use StringBuilder a while ago.
Second, as #Riggy mentioned Java actually does optimize + as long as they occur in a single expression. But if you were to do:
String s = "";
s += a;
s += b;
s += c;
s += d;
Then the effective code would become:
String s ="";
s = new StringBuilder(s).append(a).toString();
s = new StringBuilder(s).append(b).toString();
s = new StringBuilder(s).append(c).toString();
s = new StringBuilder(s).append(d).toString();
which is suboptimal to
String s = new StringBuilder(s).append(a).append(b).append(c).append(d).toString();
Because of compiler optimizations, it may or may not make any difference in your app. You'll have to run comparison speed tests to see.
But before you obsess about performance, get the program working right. "Premature optimization is the root of all evil."
I've heard that using StringBuilder is faster than using string concatenation, but I'm tired of wrestling with StringBuilder objects all of the time. I was recently exposed to the SLF4J logging library and I love the "just do the right thing" simplicity of its formatting when compared with String.format. Is there a library out there that would allow me to write something like:
int myInteger = 42;
MyObject myObject = new MyObject(); // Overrides toString()
String result = CoolFormatingLibrary.format("Simple way to format {} and {}",
myInteger, myObject);
Also, is there any reason (including performance but excluding fine-grained control of date and significant digit formatting) why I might want to use String.format over such a library if it does exist?
Although the Accepted answer is good, if (like me) one is interested in exactly Slf4J-style semantics, then the correct solution is to use Slf4J's MessageFormatter
Here is an example usage snippet:
public static String format(String format, Object... params) {
return MessageFormatter.arrayFormat(format, params).getMessage();
}
(Note that this example discards a last argument of type Throwable)
For concatenating strings one time, the old reliable "str" + param + "other str" is perfectly fine (it's actually converted by the compiler into a StringBuilder).
StringBuilders are mainly useful if you have to keep adding things to the string, but you can't get them all into one statement. For example, take a for loop:
String str = "";
for (int i = 0; i < 1000000; i++) {
str += i + " "; // ignoring the last-iteration problem
}
This will run much slower than the equivalent StringBuilder version:
StringBuilder sb = new StringBuilder(); // for extra speed, define the size
for (int i = 0; i < 1000000; i++) {
sb.append(i).append(" ");
}
String str = sb.toString();
But these two are functionally equivalent:
String str = var1 + " " + var2;
String str2 = new StringBuilder().append(var1).append(" ").append(var2).toString();
Having said all that, my actual answer is:
Check out java.text.MessageFormat. Sample code from the Javadocs:
int fileCount = 1273;
String diskName = "MyDisk";
Object[] testArgs = {new Long(fileCount), diskName};
MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0} file(s).");
System.out.println(form.format(testArgs));
Output:
The disk "MyDisk" contains 1,273 file(s).
There is also a static format method which does not require creating a MessageFormat object.
All such libraries will boil down to string concatenation at their most basic level, so there won't be much performance difference from one to another.
Plus it worth bearing in min that String.format() is a bad implementation of sprintf done with regexps, so if you profile your code you will see an patterns and int[] that you were not expecting.
MessageFormat and the slf MessageFormmater are generally faster and allocate less junk