Differrence Between strValue.toString() & strValue+"" & ""+strValue - java

Converting the value to String in java; There are multiple ways of doing it.
Just wanted to know what's the difference between each other in the following ways.
strValue.toString()
strValue+""
""+strValue

It depends on java version. Java 7 would act a bit smarter using StringBuilder + append().
Generally, you do not want unnecessary allocations. Use first one.

strValue.toString()
will return itself, because the toString() implementation of String (I'm guessing strValue is indeed of type String) returns this.
strValue+""
""+strValue
Will result in the same value (strValue) but won't invoke the toString() method

All Strings contain the same value, try it out:
String strValue = "Hello world"; // not null
String a = strValue.toString();
String b = strValue+"";
String c = ""+strValue;
Measuring its length give all the result 11, because adding an empty String to another one equals the original String itself:
System.out.println(a.length());
...
Try the equality between these Strings:
System.out.println(a.equals(b));
System.out.println(b.equals(c));
System.out.println(c.equals(a));
They are all true, because these Strings have the same value to be compared. All it in the case the strValue is not null.

One major difference is how null is handled.
If strValue is null, strValue.toString() will throw a NullPointerException, while the other two options will return the String "null".
Other differences may be observed if strValue is of a boxed numeric type, and you try to concatenate other numeric variables to it.
For example :
If
Integer a = 5;
Integer strValue = 6;
Then
a+strValue+""
would return
"11"
while
a+""+strValue
or
""+a+strValue
would return
"56"

Related

How to remove the null before resultant string after concatenation..?

How to remove the null after concatenation of two strings.
Ex:
String a = null;
String b = Hello;
a+=b;
System.out.println(a);// output is nullhello
here, i need output as only hello,
Thanks in advance.
You can use this
String a = null;
String b = "Hello";
a = ((a==null) ? "": a) + b;
System.out.println(a);
The Java designers thought it a good idea to treat the compound assignment by sum operator += when applied to a null lvalue java.lang.String reference as a special case by injecting a (rather arbitrary) textual stringification of nullness.
(I see it as a manifest act of utter madness: an alternative would include throwing a NullPointerException as would happen if += is applied to a numeric boxed type such as java.lang.Integer.)
If you don't want this behaviour then you need to program specifically to obviate it.
You can use custom method for this, this is one line of code:
public static String concat(String a, String b) {
return a == null ? b : b == null ? a : a + b;
}
It might be a bit of overhead, but you can use Objects.toString method:
String a = null;
String b = Hello;
System.out.println(Objects.toString(a,"").concat(Objects.toString(b,"")));
public static String toString(Object o,
String nullDefault)
Returns the result of calling toString on the first argument if the
first argument is not null and returns the second argument otherwise.
This will handle all the possible cases {(a == null, b!= null),(a != null, b == null),(a == null, b == null),(a != null, b!= null)}
other alternative will be using Optional
System.out.println(
Optional.ofNullable(a).orElse("")
.concat(Optional.ofNullable(b).orElse(""))
);
public T orElse(T other)
Return the value if present, otherwise return other.
This will be identical to the first solution. Both of this solutions has one common disadvantage: code needs to be duplicated for every additional variable. For example if now we need to concatenate 3 variables a,b and c. We will have to just copy and paste same code for c.
In this case we can use Streams
System.out.println(
Stream.of(a,b)
.filter(Objects::nonNull)
.collect(Collectors.joining())
);
It will create a stream consisting of strings a and b; will filter out all strings which are null and finally collect all remaining strings using empty delimiter. In case if there are more then 2 variables we will just add them to initial stream.
I hope you will find this helpful.
You may use Google's Guava library to get rid of null before concatenation.
String a = Strings.nullToEmpty(null);
String b = Strings.nullToEmpty("Hello");
a+=b;
System.out.println(a);// output is hello
It makes the code more explicit about the fact that you don't want null, IMO it's more readable as than a ternary expression.

Java comparing strings [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
i have a small of a problem. I have to String Lists with the same size and a string to compare. meaning i want to compare the string with the first list to get the index of the compared string in the list and then get another string from the other list on this index.
private String getStringOnIndex(List<String> list1, List<String> list2,String elem)
{
String elem2;
for (int i = 0; i<list1.size();i++) {
if(list1.get(i).equals(elem)){
elem2 = list2.get(i);
return elem2;
} else {
return "nope";
}
}
}
Is it wrong to compare two strings like that. or should i use the operator ==. I know the style with to string lists is not nice but its just a temporary solution. thx for any help :)
To answer your specific question on "string comparison", what you are doing is correct. String content comparison should be done using equals(). Using operator == is only checking for the equality of the reference, not the content.
For the work you are doing now, it looks like a key-value lookup to me. You may consider some redesign and, instead of storing 2 lists, make a Map<String, String>
== operator in Java compares the Object References, to compare strings you should use equals().
if (list1.get(i).matches(elem))....
always use equals method to compare two string. If you are comparing references then use == operator. Here discussion can be useful How do I compare strings in Java?
== operator work fine only if the String variable is not instanciated new keyword.
Suppose:
String s1 = "abc";
String s2 = "abc";
Then s1==s2 works good.
If:
String s1 = new String("abc");
String s2 = new String("abc");
Then you must use equals method to compare the values.
Finally, it is always better to use equals method to compare the String values.
Use the equals() method to compare the value of the object,where as == operator will compare object reference.
The problem is not equals (that is the correct method), you must remove else expression, if not you will stop always at first iteration, solution:
private String getStringOnIndex(List<String> list1, List<String> list2,String elem)
{
String elem2;
for (int i = 0; i<list1.size();i++) {
if(list1.get(i).equals(elem)){
elem2 = list2.get(i);
return elem2;
}
}
return "nope";
}

Java HashMap key comparison against string fails

I have the following situation. I have a HashMap in Java with keys as strings.
Then in some stage , in runtime I create strings equal to those keys in order to retrieve the data from that map.The strings are created as follows within "for" loop:
String keyToRetrive = "lights[" + Integer.toString(i) + "]" + ".Intensity";
The strange thing about it that when I iterate through the map to find the key that equals that string ,even when the match is found the search steps over.So in this search loop :
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
if (name == entry.getKey()) { ///name- "lights[0].Intesity"
uniformOut = (ICleanable) entry.getValue();
break;
}
}
The key with the name "lights[0].Intesity" never returns true even that the map contains one.How I solved it .I used hashCode() for both compared string values.So this version does work:
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
if (name.hashCode() == entry.getKey().hashCode()) {
uniformOut = (ICleanable) entry.getValue();
break;
}
}
UPDATE: After being pointed to the fact that "==" doesn't work good and "equals()" should be used I would like to narrow the question:Why "==" does work for strings which were not created from several concatenated blocks? I mean, if I defines key string to compare agains as a simple single string:
String foo="foo";
Such a string is compared using "==" against HashMap key all right.
I am not an expert Java programmer so can anybody explain why it works this way?
You are comparing Strings using == operator. Use equals() instead:
name.equals(entry.getKey())
This is a common pitfall in Java, see How do I compare strings in Java? and Difference between Equals/equals and == operator?.
BTW (unrelated to your problem) when concatenating strings you don't need to call toString() explicitly so this:
"lights[" + Integer.toString(i) + "]" + ".Intensity"
can be replaced with:
"lights[" + i + "]" + ".Intensity"
It'll work for i of any type, not only int.
When you compare objects using ==, you're performing a "referential equality" comparison, meaning that you're checking whether the two references point at the same String object in memory. If you're familiar with C, it would be like:
char* a = some_string();
char* b = some_other_string();
if (a == b) { ... }
On the other hand, when you compare objects using .equals(), you're performing a "structural equality" comparison, meaning that you're checking whether the two objects contain equivalent data. Again, the C analog of this would be:
char* a = some_string();
char* b = some_other_string();
if (strcmp(a, b) == 0) { ... }
Now, the thing you really, really don't want to do is to compare the two objects' hash codes. Why not? Because two objects with the same hash code are not necessarily equal! They might be, but you can't correctly rely on it.
Update: You also asked about why == works for string literals. The answer is because the Java compiler doesn't allocate constant strings on the heap; instead it stores them in the constant pool of the class in which they're used. So, if you write:
String foo1 = "foo";
String foo2 = "foo";
Then the compiler will have both references point at the same location in the class's constant pool. If, however, you write:
String foobar1 = "foobar";
String foobar2 = "foo" + bar();
String bar() { return "bar"; }
The compiler isn't quite smart enough to figure out that foobar2 is logically equivalent to foobar1. However, even if you know that the two variables are compile-time constants, you still should keep it simple and use .equals().
The others have stated why your code won't work, however:
1) If you're using a HashMap, you should use map.get(key) to retreive the value, not an interator of entries; that's the whole point of the Hash Map.
2) Use generics, avoid explicitly casting as much as you can!

Comparing two identical strings with == returns false [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
I am making an archive for my family. There are no syntax errors, however whenever I type in "Maaz", it evaluates realName == "Maaz" to false and goes to the else statement.
import java.util.Scanner;
public class MainFamily {
public static void main (String [] args) {
System.out.println("Enter you're name here");
Scanner name = new Scanner(System.in);//Scanner variable = name
String realName;
realName = name.nextLine();//String variable = user input
System.out.println("Name: "+ realName);
if (realName == "Maaz") {
System.out.println("Name: Maaz");
} else {
System.out.println("This person is not in the database");
}
}
}
TL;DR
You wrote (this doesn't work):
realName == "Maaz"
You meant this:
realname.equals("Maaz")
or this:
realname.equalsIgnoreCase("Maaz")
Explanation
In Java (and many other Object-Oriented programming languages), an object is not the same as a data-type. Data-types are recognized by the runtime as a data-type.
Examples of data-types include: int, float, short.
There are no methods or properties associated with a data-type. For example, this would throw an error, because data-types aren't objects:
int x = 5;
int y = 5;
if (x.equals(y)) {
System.out.println("Equal");
}
A reference is basically a chunk of memory that explicitly tells the runtime environment what that data-block is. The runtime doesn't know how to interpret this; it assumes that the programmer does.
For example, if we used Integer instead of int in the previous example, this would work:
Integer x = new Integer(5);
Integer y = new Integer(5);
if (x.equals(y)) {
System.out.println("Equal");
}
Whereas this would not give the expected result (the if condition would evaluate to false):
Integer x = new Integer(5);
Integer y = new Integer(5);
if (x == y) {
System.out.println("Equal");
}
This is because the two Integer objects have the same value, but they are not the same object. The double equals basically checks to see if the two Objects are the same reference (which has its uses).
In your code, you are comparing an Object with a String literal (also an object), which is not the same as comparing the values of both.
Let's look at another example:
String s = "Some string";
if (s == "Some string") {
System.out.println("Equal");
}
In this instance, the if block will probably evaluate to true. Why is this?
The compiler is optimized to use as little extra memory as is reasonable, although what that means depends on the implementation (and possibly runtime environment).
The String literal, "Some string", in the first line will probably be recognized as equivalent to the String literal in the second line, and will use the same place in memory for each. In simple terms, it will create a String object and plug it into both instances of "Some string". This cannot be relied upon, so using String.equals is always a better method of checking equivalence if you're only concerned with the values.
do this instead
if (realName.equals("Maaz"))
equals() should be used on all non-primitive objects, such as String in this case
'==' should only be used when doing primitive comparisons, such as int and long
use
if(realName.equals("Maaz"))
use == with primitive data type like int boolean .... etc
but if you want to compare object in java you should use the equals method
You have to compare objects with realName.equals ("Maaze"), not with ==.
It is best practice to compare Strings using str.equals(str2) and not str == str2. As you observed, the second form doesn't work a lot of the time. By contrast, the first form always works.
The only cases where the == approach will always work are when the strings are being compared are:
string literals or references to string literals, or
strings that have been "interned" by application-level code calling str = str.intern();.
(And no, strings are not interned by default.)
Since it is generally tricky to write programs that guarantee these preconditions for all strings, it is best practice to use equals unless there is a performance-related imperative to intern your strings and use ==.
Before that you decide that interning is a good idea, you need to compare the benefits of interning with the costs. Those costs include the cost of looking up the string in the string pool's hash table and the space and GC overheads of maintaining the string pool. These are non-trivial compared with the typical costs of just using a regular string and comparing using equals.
You can also use
realname.equalsIgnoreCase("Maaz")
This way you can accept Maaz, maaz, maaZ, mAaZ, etc.
== tests shallow equality. It checks if two objects reference the same location in memory.
Intriguing. Although, as others have stated, the correct way is to use the .equals(...) method, I always thought strings were pooled (irrespective of their creation). It seems this is only true of string literals.
final String str1 = new String("Maaz");
final String str2 = new String("Maaz");
System.out.println(str1 == str2); // Prints false
final String str3 = "Laaz";
final String str4 = "Laaz";
System.out.println(str3 == str4); // Prints true
Since you are working on strings, you should use equals to equalsIngnorecase method of String class. "==" will only compare if the both objects points to same memory location, in your case, both object are different and will not be equal as they dont point to same location. On the other hand, equals method of String class perform a comparison on the basis of the value which objects contains. Hence, if you will use equals method, your if condition will be satisfied.
== compares object references or primitive types (int, char, float ...)
equals(), you can override this method to compare how both objects are equal.
for String class, its method equal() will compare the content inside if they are the same or not.
If your examples, both strings do not have the same object references, so they return false, == are not comparing the characters on both Strings.
It seems nobody yet pointed out that the best practice for comparing an object with a constant in Java is calling the equals method of the constant, not the variable object:
if ("Maaz".equals (realName)) {}
This way you don't need to additionally check if the variable realName is null.
if(realName.compareTo("Maaz") == 0) {
// I dont think theres a better way do to do this.
}

Concatenating null strings in Java [duplicate]

This question already has answers here:
String concatenation with Null
(3 answers)
Closed 3 years ago.
Why does the following work? I would expect a NullPointerException to be thrown.
String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
Why must it work?
The JLS 5, Section 15.18.1.1 JLS 8 § 15.18.1 "String Concatenation Operator +", leading to JLS 8, § 5.1.11 "String Conversion", requires this operation to succeed without failure:
...Now only reference values need to be considered. If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l). Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.
How does it work?
Let's look at the bytecode! The compiler takes your code:
String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
and compiles it into bytecode as if you had instead written this:
String s = null;
s = new StringBuilder(String.valueOf(s)).append("hello").toString();
System.out.println(s); // prints "nullhello"
(You can do so yourself by using javap -c)
The append methods of StringBuilder all handle null just fine. In this case because null is the first argument, String.valueOf() is invoked instead since StringBuilder does not have a constructor that takes any arbitrary reference type.
If you were to have done s = "hello" + s instead, the equivalent code would be:
s = new StringBuilder("hello").append(s).toString();
where in this case the append method takes the null and then delegates it to String.valueOf().
Note: String concatenation is actually one of the rare places where the compiler gets to decide which optimization(s) to perform. As such, the "exact equivalent" code may differ from compiler to compiler. This optimization is allowed by JLS, Section 15.18.1.2:
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.
The compiler I used to determine the "equivalent code" above was Eclipse's compiler, ecj.
See section 5.4 and 15.18 of the Java Language specification:
String conversion applies only to the
operands of the binary + operator when
one of the arguments is a String. In
this single special case, the other
argument to the + is converted to a
String, and a new String which is the
concatenation of the two strings is
the result of the +. String conversion
is specified in detail within the
description of the string
concatenation + operator.
and
If only one operand expression is of
type String, then string conversion is
performed on the other operand to
produce a string at run time. The
result is a reference to a String
object (newly created, unless the
expression is a compile-time constant
expression (§15.28))that is the
concatenation of the two operand
strings. The characters of the
left-hand operand precede the
characters of the right-hand operand
in the newly created string. If an
operand of type String is null, then
the string "null" is used instead of
that operand.
The second line is transformed to the following code:
s = (new StringBuilder()).append((String)null).append("hello").toString();
The append methods can handle null arguments.
You are not using the "null" and therefore you don't get the exception. If you want the NullPointer, just do
String s = null;
s = s.toString() + "hello";
And I think what you want to do is:
String s = "";
s = s + "hello";
This is behavior specified in the Java API's String.valueOf(Object) method. When you do concatenation, valueOf is used to get the String representation. There is a special case if the Object is null, in which case the string "null" is used.
public static String valueOf(Object obj)
Returns the string representation of the Object argument.
Parameters:
obj - an Object.
Returns:
if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.

Categories