My requirement is to store the large chunk of data (String value) but i am confused which one is better to use. I only want to append the incoming data.
e.g. String str1 = "abc"
String str2 = "123";
String Str3 = "xyz";
suppose i am appending/ adding to (Sbuilder/SBuffer/ vector/ ArrayList)
one after another,
e.g. str1, str2 str3 then output must be "abc123xyz"
str2, str1,str3 output must be "123abcxyz"
Use StringBuilder and ArrayList
StringBuffer and Vector have thread synchronization that adds overhead (unless you need it, but even then there's ways to add that to the newer classes)
From the javadoc for StringBuffer:
The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.
Also, I think the Vector is backed internally by an Array as well, and is pretty much deprecated. If you want fast appends then you might want to take a look at LinkedList (it is slightly faster than ArrayList for pure appends because you don't have to grow the backing Array periodically).
However, if this is just for sequences of characters then the StringBuilder is optimized for exactly this case, and you shouldn't muck around with Collections with all of their overhead.
If you don't need to synchronize you can avoid StringBuffer and Vector and prefer StringBuilder and ArrayList instead.
Whether to use StringBuilder or ArrayList depends on your requirements. If you just want to concatenate the strings SB is enough.
If data size is variable in that case we used StringBuffer because the StringBuffer class is designed to create and manipulate dynamic string information. The memory allocated to the object is automatically.
If you are doing this inside a single thread you will want to use a StringBuilder over anything when all you want to achieve is string concatenation; for multiple types use an ArrayList.
Related
In an interview, I want to build up a new String with some substrings. I argued that ArrayList<String> is almost the same as StringBuilder, but the interviewer said I should always use StringBuilder if I need to deal with String. I think the time complexity of adding/removing functions between them are the same.
They aren't the same thing at all. StringBuilder builds a single string, while ArrayList<String> is just that--an array of separate strings. Of course, you can concatenate all of the array's strings with String.join("", list), where the first argument is the separator that you want to use, but why would you go that route instead of just using the class that was designed to do exactly what you're trying to do in the first place?
It all comes down to memory consumption. String is an object, while ArrayList<String> holds separate objects, StringBuilder holds only one.
StringBuilder has a member function to return the whole built string, whereas in ArrayList, you have to concatenate the strings yourself.
Unless you continue to need the separate elements you are adding to the list, you should use a StringBuilder.
After all, you can't directly get a concatenated string from the contents of the list: you have to put it in, say, a StringBuilder.
But in the specific case of building up a string of substrings, StringBuilder provides methods to allow you to append portions of Strings without using substring: the append(CharSequence, int, int) method is an optimization to avoid creating that extra string.
It should be mentioned that, at least when I have written python, it has been considered better to build up a list, and then use ''.join(theList) at the end, which is basically the analog of ArrayList<String>.
I don't know enough about python to know why this is considered particularly better.
You can "build" strings using both. However StringBuilder is a class specializing in building strings with its append insert delete charAt etc... methods. An ArrayList is a general purpose collection which lacks most of this functionality. Consider implementing the following (contrived example) with an ArrayList:
StringBuilder sb = new StringBuilder().append("time: ")
.append(System.currentTimeMillis())
.deleteCharAt(4)
.reverse();
System.err.println(sb); // 3153067310451 emit
Ergonomics and readability aside, there are performance considerations but those are largely irrelevant on trivially sized examples.
If you need a single String at the end, performance and memory consumption are some differences for sure. Whenever you build a String from parts, in the good case you end up using StringBuilder, or in a slightly worse case StringBuffer, and in the worst case you end up concatenating two strings, then throw them away, and repeat - lots of allocations and garbage collection in this case.
JLS12 still mentions StringBuffer by name for optimization (but hopefully StringBuilder is used internally, as similar technique):
An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
In the particular case of having a List<String> and later using String.join() on it, StringJoiner contains the particular StringBuilder object which is going to be used.
So there will be a builder anyway, and then it may be more efficient to use it from the beginning.
Why do I need to redefine the variable theString if I use the method replace in this code :
String theString = "I w#nt to h#ve the regul#r \"A\"!";
theString = theString.replace("#", "a");
System.out.println(theString);
Why can't I do :
theString.replace("#", "a");
and that's it?
Strings are immutable -- you cannot change them once they have been created. There are exceptions of course, if you use reflective magic, but for the most part, they should be treated as invariants. So therefore the method replace(...) does not change the String, it can't, but rather it creates and returns a new String. So to be able to use that new String, you have to get access to its reference, and that can be done by assigning it to a String variable or even to the original String variable. This discussion gets to the heart of what is the difference between an object and a reference variable.
Because String objects are, by design, immutable, so you need to create a new String to contain your changes
The posted answers mention the technical reason (strings are immutable) but neglect to mention why it is that way. See this: Why are strings immutable in many programming languages?
Taken from this link
In Java, String is not implemented as character arrays as in other programming languages. Instead string is implemented as instance of String class.
Strings are constants/ immutable and their values cannot be changed after they are created. If any operations that results in the string being altered are performed a new instance of String object is created and returned. This approach is done for implementation efficiency by Java.
It is recommended to use StringBuffer or StringBuilder when many changes need to be performed on the String. StringBuffer is like a String but can be modified. StringBuffer is thread safe and all the methods are synchronized. StringBuilder is equivalent to StringBuffer and is for use by single thread. Since the methods are not synchronized it is faster.
Assume that we have a StringBuilder or StringBuffer like below:
StringBuilder s1 = new StringBuilder("xxx");
StringBuffer s2 = new StringBuffer("xxx");
We can get a String from the above variables using the toString() method.
I know that toString is an over-ridden method in both classes.
Assume also that we have a String like below:
String s3 = "xxx";
I can't get a StringBuilder or StringBuffer using toStringBuilder() or toStringBuffer(). Instead, the way we can achieve is like below:
StringBuilder sb = new StringBuilder(s3);
Is there a reason why toStringBuilder()/toStringBuffer() is not defined and is there any other effective way to get a StringBuilder/StringBuffer from String.
String itself is immutable. That has many advantages, especially with concurrent usage, sharing substrings and such.
Also back and forth coupling between classes is bad design.
toString is a method that is part of the Object class and thus all classes of java will have such method. A String is immutable and as such both toStringBuilder and toStringBuffer will create new objects. I think that if there were such methods many users would be mislead that using these methods they can modify the string in-place. Also because of the same reasons there can not possible be any more efficient way to create a StringBuilder/StringBuffer.
You might ask for a considerable number of String.toFoo() methods, and where to draw the line? You can construct StringBuilder and StringBuffer using the constructor. That's enough - why add another method?
Everyone knows that Java's String object is immutable which essentially means that if you take String object a and concatenate it with another String object, say b, a totally new String object is created instead of an inplace concatenation.
However, recently I have read this question on SO which tells that the concatenation operator + is replaced with StringBuilder instances by the compiler.
At this point, I get a bit confused since, as far as I know and think, the StringBuilder objects are mutable due to their internal structure. In this case, wouldn't this essentially make String objects in Java mutable ?
Not really.
The actual Strings are still immutable, but in compile time, the JVM can detect some situations where the creation of additional String objects can be replaced by a StringBuilder.
So if you declare a String a and concatenate with another String, your a object doesn't change, (since it's immutable), but the JVM optimizes this by replacing the concatenation with the instantiation of a StringBuilder, appending both Strings to the Builder, and finally assigning the resulting String.
Let's say you have:
String a = "banana";
String d = a + "123" + "xpto";
Before the JVM optimized this, you would essentially be creating a relatively large number of Strings for something so simple, namely:
String a
String "123"
String "xpto"
String a + "123"
String a+"123"+"xpto"
With the optimization of transforming concatenation into a StringBuilder, the JVM no longer needs to create the intermediate results of the concatenation, so only the individual Strings and the resulting one are needed.
This is done basically for performance reasons, but keep in mind that in certain situations, you'll pay a huge penalty for this if you aren't careful. For instance:
String a = "";
for(String str: listOfStrings){
a += str;
}
If you were doing something like this, in each iteration the JVM will be instantiating a new StringBuilder, and this will be extremely costly if listOfStrings has a lot of elements. In this case, you should use a StringBuilder explicitly and do appends inside the loop instead of concatenating.
Strings are immutable objects. Once you concatenate it with another String, it becomes a new object. So remember - you don't change the existing String, you just create a new one.
Strings really are immutable. The compiler may generate code involving StringBuilder, but that is just an optimization which does not change how the code behaves (apart from performance). If there was some case where you could observe mutation (e.g. by keeping a reference to one of the intermediate results), the compiler would have to optimize in a way that still gives you an immutable string for that intermediate reference.
So if StringBuilder is used under the covers, even if you can't directly see the difference, doesn't that still mean that mutability is involved? Well, yes, but if you get down to it all the RAM in your PC is mutable. The memory of immutable objects can be moved around by the garbage collector, which definitely involves mutation as well. In the end, the important thing to you as a programmer is that this mutation is hidden from you, and you get a big promise that your program will behave the way you expect, i.e. you'll never see mutation in an immutable object (except in cases of severe problems, e.g. faulty RAM).
Is using a String() constructor as against string literal beneficial in any scenario?
Using string literals enable reuse of existing objects, so why do we need the public constructor? Is there any real world use?
For eg., both the literals point to the same object.
String name1 = "name";//new String("name") creates a new object.
String name2 = "name";
One example where the constructor has a useful purpose: Strings created by String.substring() share the underlying char[] of the String they're created by. So if you have a String of length 10.000.000 (taking up 20MB of memory) and take its first 5 characters as substring then discard the original String, that substring will still keep the 20MB object from being eligible for garbage collection. Using the String constructor on it will avoid that, as it makes a copy of only the part of the underlying char array that's actually used by the String instance.
Of course, if you create and use a lot of substrings of the same String, especially if they overlap, then you'd very much want them to share the underlying char[], and using the constructor would be counterproductive.
Since string is immutable, operations like substring keep the original string that might be long. Using the constructor to create new string from the substring will create a new string and will allow dropping the old string (to GC). This way might free up needed memory.
Example:
String longS = "very long";
String shortS = new String(longS.substring(4));
Because sometimes you might want to create a copy and not just have a new reference to the same string.
All good answers here, but I think it's worth pointing out that the Java treats literals quite different than Strings constructed the traditional way.
This is a good Q/A about it.