Are string literal created every time? - java

So I was reading orcale java tutorials and I read
In this case, "Hello world!" is a string literal—a series of characters in your code that is enclosed in double quotes. Whenever it encounters a string literal in your code, the compiler creates a String object with its value
I want to make sure that am not creating random values all the time but this confused me, so does this mean that every time I use a string literal, a string object is created?
For example if I want to avoid creating new objects
String message = "am a NOT new string"
for(int i = 0; i < 1000; i++)
{
someStringarray[i] = message;
}
is more efficient than
for(int i = 0; i < 1000; i++)
{
someStringarray[i] = "am a new string EVERY time";
}

In Java, any instance of the same string literal always evaluates to the same object. In other words, in both of the above cases, there will only be one String object created, and the array will be filled in by having each entry reference that one string. There should not be an appreciable performance difference between the two.
Hope this helps!

"Whenever" is as seen by the compiler, not as seen by your program. The compiler sees the string "am a new string EVERY time" exactly once, when it compiles line 3 of your program. So there's only one copy of it.
In general, you know you're creating a new object because you use the new keyword (or you call a function which does).

All compile time string literals are interned(Java).
In the first case there is only one string in the memory and lots of pointers.
The second case is identical.
Wikipedia - String Interning

using it like you are at compile time the string table is created once at compile time and not repeated for each string, if you do create large arrays all pointing to the same object your are still using memory for the array itself. If you use StringBuffer type object or new() or take input from console then you would be using the heap and memory

Related

Java concatenate strings vs static strings

I try to get a better understanding of Strings. I am basically making a program that requires a lot of strings. However, a lot of the strings are very, very similar and merely require a different word at the end of the string.
E.g.
String one = "I went to the store and bought milk"
String two = "I went to the store and bought eggs"
String three = "I went to the store and bought cheese"
So my question is, what approach would be best suited to take when dealing with strings? Would concatenating 2 strings together have any benefits over just having static strings in, say for example, performance or memory management?
E.g.
String one = "I went to the store and bought "
String two = "milk"
String three = "cheese"
String four = one + two
String five = one + three
I am just trying to figure out the most optimal way of dealing with all these strings. (If it helps to put a number of strings I am using, I currently have 50 but the number could surplus a huge amount)
As spooky has said the main concern with the code is readability. Unless you are working on a program for a phone you do not need to manage your resources. That being said, it really doesn't matter whether you create a lot of Strings that stand alone or concatenate a base String with the small piece that varies. You won't really notice better performance either way.
You may set the opening sentence in a string like this
String openingSentence = "I went to the store and bought";
and alternate defining each word alone, by defining one array of strings like the following ::
String[] thingsToBeBought = { "milk", "water", "cheese" .... };
then you can do foreach loop and concatenate each element in the array with the opening sentence.
In Java, if you concatenate two Strings (e.g. using '+') a new String is created, so the old memory needs to be garbage collected. If you want to concatenate strings, the correct way to do this is to use a StringBuilder or StringBuffer.
Given your comment about these strings really being URLs, you probably want to have a StringBuilder/StringBuffer that is the URL base, and then append the suffixes as needed.
Performance wise final static strings are always better as they are generated during compile time. Something like this
final static String s = "static string";
Non static strings and strings concatenated as shown in the other example are generated at runtime. So even though performance will hardly matter for such a small thing, The second example is not as good as the first one performance wise as in your code :
// not as good performance wise since they are generated at runtime
String four = one + two
String five = one + three
Since you are going to use this string as URL, I would recommend to use StringJoiner (in case your are using JAVA 8). It will be as efficient as StringBuilder (will not create a new string every time you perform concatenation) and will automatically add "/" between strings.
StringJoiner myJoiner = new StringJoiner("/")
There will be no discernable difference in performance, so the manner in which you go about this is more a matter of preference. I would likely declare the first part of the sentence as a String and store the individual purchase items in an array.
Example:
String action = "I went to the store and bought ";
String [] items = {"milk", "eggs", "cheese"};
for (int x = 0; x< items.length; x++){
System.out.println(action + items[x]);
}
Whether you declare every possible String or separate Strings to be concatenated isn't going to have any measurable impact on memory or performance in the example you give. In the extreme case of declaring truly large numbers of String literals, Java's native hash table of interned Strings will use more memory if you declare every possible String, because the table's cached values will be longer.
If you are concatenating more than 2 Strings using the + operator, you will be creating extra String objects to be GC'd. For example if you have Strings a = "1" and b = "2", and do String s = "s" + a + b;, Java will first create the String "s1" and then concatenate it to form a second String "s12". Avoid the intermediate String by using something like StringBuilder. (This wouldn't apply to compile-time declarations, but it would to runtime concatenations.)
If you happen to be formatting a String rather than simply concatenating, use a MessageFormat or String.format(). It's prettier and avoids the intermediate Strings created when using the + operator. So something like, String urlBase = "http://host/res?a=%s&b=%s"; String url = String.format(urlBase, a, b); where a and b are the query parameter String values.

Java Core: data type for variable of changing value

it's a bit of a nooby question, but say I've got a variable that keeps getting re-initialized within a loop, what would be the best data-type to store that data temporarily?
for example:
String value = "";
while(file.hasNext()){
value = file.readLine();
}
The reason I ask is that I know that Strings are immutable, which suggests that there is a more efficient alternative, am I right?
The reason I ask is that I know that Strings are immutable, which suggests that there is a more efficient alternative, am I right?
Nope. You're calling readLine multiple times, that's going to give you a different string reference each time. Just because the string content itself can't be changed doesn't mean that it's inefficient to change the value of a String variable. That variable value is just a reference... it's not like it's going to copy the string content on each iteration.
Do you even need the variable to be declared in the loop? Generally, I prefer to declare variables with the narrowest scope possible:
while (file.hasNext()) {
String line = file.readLine();
// Use line here
}
In this kind of case, the best thing to do is to all the computation line by line in the while loop, i.e.
String value;
while(file.hasNext()) {
value = file.readLine();
//do your thing on value
//or store data in an appropriate structure
}
If you really need to have a string containing your entire file, and you are not able to the data while reading it, the best thing to use is StringBuilder, see documentation.
In your case, it would give:
StringBuilder sb = new StringBuilder();
while(file.hasNext()) {
sb.append(file.readLine());
}
String entireFile = sb.toString();

Is String Builder or ""+someNumb more efficient/correct for small cases?

II've been in the habit of doing:
int num = 12;
String text = ""+12;
for a long time, but I've found that to be a very inefficient mechanism for the large number of additions.
For those cases I generally do something like:
// this is psuedo code here..
FileInputStream fis = new FileInputStream(fis);
StringBuilder builder = new StringBuilder();
while(input.hasNext()) {
builder.append(input.nextString());
}
My question is: When coding for Android (vs the General Java case) Is the performance trade off at the small case worth using String Builder, or are there any other reasons to prefer String Builder in these small cases? It seems like it's a lot of extra typing int he simple case presented above. I also suspect (though I have not confirmed) that the memory allocations in the simple case are probably not worth it.
Edit: Suppose that the values being appended aren't known at compile time, I.E. they aren't constants.
Also the example above of ""+12 is a poorly chosen example.. Suppose it was
String userGeneratedText = textInput.getText().toString();
int someVal = intInput.getInt();
String finalVal = userGeneratedText+someVal;
If your code is short as you shown here:
String text = "foo" + 12;
The compiler will automatically replace the concatenation to use StringBuilder:
String text = new StringBuilder().append("foo").append(12).toString();
So don't worry about the inefficiency of this code, because it will work better than you expect.
For cases when you need to append very large Strings or you don't know how many objects (Strings, ints, booleans, etc) will you concatenate, use a StringBuilder as you do in your second code sample.
Here's a more in depth explanation about how the String concatenation works: http://blog.eyallupu.com/2010/09/under-hood-of-java-strings.html
As far as I know! string is immutable object. It means that its state cannot be changed, when ever you append value to string type then what happened is compiler deletes old one create new one with apended value.
But this is not the case with StringBuilder. StringBuilder is mutable which means its old value won't be destroyed. Any change/append will be taken place with existing object.
I know I am not covering in depth but this might cause major performance difference.

Convert code with pointers in C to Java code

I am having some difficulty in understanding how to write the below piece of code using String or char[] in Java.
void xyz(char *a, int startIndex, int endIndex)
{
int j;
for (j = startIndex; j <= endIndex; j++)
{
doThis((a+startIndex), (a+j));
xyz(a, startIndex+1, endIndex);
}
}
Here char *a points to the starting location of the char name[]
The above are just some random functions, but I just want the logic of how to use char* and character index char[] in Java
Based on the rephrased question from the comment thread:
You cannot change the characters of a Java String. If you need to modify a sequence of characters, use StringBuilder, which supports setCharAt(int, char), insert(int, char), and append(char). You can use new StringBuilder(myString) to convert a String to a StringBuilder, and stringBuilder.toString() to convert back.
This is perfectly legit Java code -- it's not code smelly, it's just the way you work with mutable character sequences.
A char* in C is, as you noted, pointing to the start of your character array (which is how C manages Strings).
In C the size of a char is one byte, and pointers always point to the start of a byte. Your C String is an array of characters, so adding 1 to a pointer moves the start of your string right by one character.
That means that the C code:
char *a;
// Set the String here
a = a + 1;
translates in Java to something like:
String a;
// Set the String here
a = a.substring(1);
or if you are using a char array:
char[] a;
// Set the array contents here
char[] copyTo = new char[a.length];
System.arraycopy(a, 1, copyTo, 0, a.length);
a = copyTo;
Java will be a bit more careful of protecting you that C will be though. For instance, if you have a zero length string, the C code has the potential to either segfault (crashing the application) or give you a gibberish string full of memory junk (then, eventually, crash the application), whereas the Java code will throw an exception (normally an IndexOutOfBoundsException) which you can, hopefully, handle cleanly.
Remember though, that String in Java are immutable. You cannot change them, you can only create new Strings. Fortunately, String has several built in functions which allow you to do a lot of the standard actions, like replace part of the String with another and return the result. A character array is mutable, and you can change the characters within them, but you will lose a lot of the nice benefits you get from using the proper String class.
Simple Answer:
You can't do exactly that. Java is pass by reference only. You don't have access to memory location information, so you can't do arithmetic with it.
Longer Answer:
It looks like you are passing in a string for manipulation. You have several options to simulate that.
You can convert the string to an array of characters and then pass in a char[]. If your manipulations are not any sort of standard string operation and completely custom this is probably what you need to do. Keep in mind that you can't change the size of the array passed in, nor can you have a point at a new array after the function completes. (again, only pass by value). Only the values of the existing elements of the array can be modified.
You can pass in the String and use the String methods, such as subString() (which your begin and end indexes seem to suggest, but this may not meet your needs. Note that strings are immutable however, and you can only get a result out via the return statement.
If you really need to modify the contents of the object passed in you can pass a StringBuilder, StringBuffer or CharBuffer object and modify away.
There's a hack that can also be used to circumvent pass by reference, but it's poor style except in special situations. Pass in an array of whatever you need to modify, so in this case an array of array of characters would allow you to set a new sub-array, and effectively acheive pass by reference, but try not to do this :)
If your method modifies the values you cant use String as that is immutable, you can use StringBuilder instead.
If your methods already rely on char arrays and you need the offsets you can use a CharBuffer to wrap an array. It does not support String operations but supports views for sub ranges, which seems to be what you use in the doThis() method.

String can't change. But int, char can change

I've read that in Java an object of type String can't change. But int and char variables can. Why is it? Can you give me an example?
Thank you.
(I am a newer -_- )
As bzabhi said, strings are immutable in Java. This means that a string object will never change. This does not mean you can not change string variables, just that you cannot change the underlying memory representation of the string. for an example:
String str = "Hello";
str += " World!";
Following the execution of these lines, str will point to a new string in memory. The original "Hello" string still exists in memory, but most likely it will not be there for long. Assuming that there are no extenuating circumstances, nothing will be pointing at the original string, so it will be garbage collected.
I guess the best way to put this would be to say that when line 2 of the example executes, a new string in memory is created from the concatenation of the original string and the string being added to it. The str variable, which is just a reference to a memory location, is then changed to point at the new variable that was just created.
I am not particularly knowledgeable on the point, but, as I understand it, this is what happens with all "non-primitive" values. Anything that at some point derives from Object follows these rules. Primitive values, such as ints, bools, chars, floats and doubles allow the actual value in memory to be changed. So, from this:
int num = 5;
num += 2;
the actual value in memory changes. Rather than creating a new object and changing the reference, this code sample will simply change the value in memory for the num variable.
As for why this is true, it is simply a design decision by the makers of Java. I'm sure someone will comment on why this was made, but that isn't something I know.
int and char can't change either. As with strings, you can put a different value into the same variable, but an integer itself doesn't change. 3 will always be 3; you can't modify it to be 4.
String is an immutable type (the value inside of it cannot change). The same is true for all primitive types (boolean, byte, char, short, int, long, float, and double).
int x;
String s;
x = 1;
x = 2;
s = "hello";
s = "world";
x++; // x = x + 1;
x--; // x = x - 1;
As you can see, in no case can you alter the constant value (1, 2, "hello", "world") but you can alter where they are pointing (if you warp your mind a bit and say that an int variable points at a constant int value).
I'm not sure that it is possible to show (by example) that Strings cannot change. But you can confirm this by reading the description section of Javadoc for the String class, then reading the methods section and noting that there are no methods that can change a String.
EDIT: There are many reasons why Strings are designed to be immutable in Java. The most important reason is that immutable Strings are easier to use correctly than mutable ones. And if you do need the mutable equivalent of a String for some reason, you can use the StringBuilder (or StringBuffer) class.
It's also worthwhile to note that since strings are immutable, that if they are passed into a method, they can't be modified inside of the method and then have those changes seen outside of the method scope.
public void changeIt(String s) {
// I can't do anything to s here that changes the value
// original string object passed into this method
}
public void changeIt(SomeObject o) {
// if SomeObject is mutable, I can do things to it that will
// be visible outside of this method call
}
This little article can probably explain it better than I can: http://www.jchq.net/tutorial/09_02Tut.htm
Strings are immutable in java. Nevertheless, you can still append or prepend values to strings. By values, I mean primitive data types or other strings.
However, a StringBuffer is mutable, i.e. it can be changed in memory (a new memory block doesn't have to be allocated), which makes it quite efficient. Also, consider the following example:
StringBuffer mystringbuffer = new StringBuffer(5000);
for (int i = 0; i<=1000; i++)
{
mystringbuffer.append ( 'Number ' + i + '\n');
}
System.out.print (mystringbuffer);
Rather than creating one thousand strings, we create a single object (mystringbuffer), which can expand in length. We can also set a recommended starting size (in this case, 5000 bytes), which means that the buffer doesn't have to be continually requesting memory when a new string is appended to it.
While a StringBuffer won't improve efficiency in every situation, if your application uses strings that grow in length, it would be efficient. Code can also be clearer with StringBuffers, because the append method saves you from having to use long assignment statements.

Categories