Weird Java Behaviour in string comparison [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Java string comparison?
I have encounter the following problem, I have an object called "lang", is a result from a method LanguageDetector.detect() which output a string.
lang = LanguageDetector.detect();
So I would want to check whether the language is english, so I am checking,
lang == "en"
The following screen is my debug screen, my lang is showing "en", however my lang == "en" is showing false and lang.toString() == "en" is false, does anyone encounter following problem before and have a possible solution?

Use equals() method of String object instead of direct comparison.
String first = new String("Hello");
String second = new String("Hello");
first == second will return false.
first.equals(second) will return true.

In Java, == always does a reference comparison. You need a value comparison though (with the equals() method for instance).

You're comparing the references to the Strings rather than the contents of the strings themselves. See here for more info.
Note that this issue doesn't apply just to Strings, but to all objects. As such, you may have to define appropriate equals() methods for any objects you create yourself.
Additionally String interning will confuse matters if you're not careful. See here for more details.

Use lang.equals("en") instead of lang == "en". The latter compares the two string references for equality, whereas the former compares the contents of the two strings.
See http://www.devdaily.com/java/edu/qanda/pjqa00001.shtml for an overview of different string comparison methods in Java.

By using == you are checking that both string references point to the same object.
For strings that are created on the fly, and not interned, this will equal false.
To compare the strings for equality, letter by letter, use string1.equals(string2) or even string1.equalsIgnoreCase(string2).

Use "en".equals(lang) instead of lang == "en"

Its better to use the equals as said
but if its necessary for performance reasons you can try
the intern() function.
lang.intern() == "en"

Related

Why doesn't the creation of a new String use intern() by default?

I have read about intern() and almost everywhere it is written that it will speed up string comparison by using == instead of equals().
String a = new String("1");
String b = new String("1");
If I am right, the code above will create 2 strings in string pool. But after reading about intern, I don't see a reason to save 2 strings with the same value in the pool.
So the question is: why doesn't java use intern() by default?
If possible I would like to get a detailed explanation.
If I am right, code above will create 2 strings in string pool.
Not in the string pool, no. That produces one string in the string pool (because of the string constant "1") and two strings elsewhere in memory (because of the two calls to new String).
why java doesn't use intern by default?
Because there's no need to do it by default. Interning a string requires work (finding the existing entry if any, adding it if not there). If the strings are transient (as many are), that's unnecessary work. Thus, leave it to the programmer, who will call intern if appropriate.
...almoust everywhere written that it will speed up string comparition by using == instead equals()
I have no idea where this "almost everywhere" is, but using == to compare strings is just plain wrong in Java. == compares object references. While it's true (I think) that if you interned each and every string and never once forgot, then == would be reliable (I think), it's not best practice at all. Use equals. That's what it's for. :-) It will, after all, start by doing == to see if the two strings being compared are the same object, and only if that's false go on to compare the actual characters...
Just a side note: There's almost never any reason to explicitly call new String(String) (there are other overloads of the constructor that are definitely useful, for instance when you need to convert an array of bytes into a string using a particular charset).

Difference in string comparison result b/w == and String#replace with == [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
String comparison and String interning in Java
I have small doubt regarding String comparisons in Java, consider the following code:
if("String".replace('t','T') == "String".replace('t','T')) {
System.out.println("true");
}
else {
System.out.println("false");
}
The above code always print's false, where as if I try like this:
if("STring" == "STring") {
System.out.println("true");
}
else {
System.out.println("false");
}
It will always print me true. Yes, I know String comparisons should be done with String.equals() or equalsIgnoreCase() method. But this is one of the question was asked in interview and I am confused. Can anyone guide me on this behavior?
As per my knowledge, in code snippet 1, "String.replace('t','T') is returning object, so object comparisons returns in false. Am I right?
"String.replace('t','T') is returning object, so object comparisons
returns in false. Am I right?
Yes, as for this case, you are right. String#replace(or any method of String class for that matter), will return a new String object (You can guess why? Immutability). And thus you would have to do the comparison using equals method, to compare their contents.
Now, in the second case: -
"STring" == "STring"
You are comparing two string literals. Now, since String literals are interned in Java, so both the literals are same (in the sense, they point to the same memory location), and hence == comparison gives you true.
The difference in comparison using == and equals is that, == compares the reference value - i.e value of memory location of objects, which will be different for two different string objects, as you are having in first case. Whereas, equals compares the actual content in those objects.
"String.replace('t','T') is returning object, so object comparisons
returns in false. Am I right?
Yes, == compares object references, and your first code is comparing two different objects.
As far as the second code is concerned its due to string interning.
ok lets do it like this, your both String objects "String" are referering to the same object.
So they are "basicly" equal. That is a thing the compiler does for you
but the method replace, does create and return a new String object, and that is why your second code is not equal.
Java always compares the basic types (int, byte, etc) or references for objects when using ==.
The java compiler optimizes the two string constants you entered to use the same object, thus the same reference, thus the == return true
DO this way
("String".replace('t','T').Tostring() == ("String".replace('t','T')).ToString()
This will solve your problem because the replace statement should be converted to string before eveluation.
You can also user the String.Equals for this or better you use ignore case as you mention in your question.
Try this:
if(string1.equals(string2)){
...
}

Java substring.equals versus ==

Using the standard loop, I compared a substring to a string value like this:
if (str.substring(i, i+3) == "dog" ) dogcount++;
and it broke the iteration. After the first increment, no further instances of "dog" would be detected.
So I used substring.equals, and that worked:
if (str.substring(i, i+3).equals("dog")) dogcount++;
My question is, why? Just seeking better understand, thx.
You should use equals() instead of == to compare two strings.
s1 == s2 returns true if both strings point to the same object in memory. This is a common beginners mistake and is usually not what you want.
s1.equals(s2) returns true if both strings are physically equal (i.e. they contain the same characters).
== compares references. You want to compare values using equals() instead.
For String comparison, always use equals() method. Because comparing on == compares the references.
Here's the link for further knowledge.
You might also want to read this for understanding difference between == and equals() method in a better way along with code examples.
== compares references(storage location of strings) of strings
and
.equals() compares value of strings
"String" is an object in Java, so "==" compares the references, as stated.
However, code like
String str1 = "dog";
String str2 = "dog";
if(str1==str2)
System.out.println("Equal!");
will actually print out "Equal!", which might get you confused. The reason is that JVM optimizes your code a little bit when you assign literals directly to String objects, so that str1 and str2 actually reference the same object, which is stored in the internal pool inside JVM. On the other hand, code
String str1 = new String("dog");
String str2 = new String("dog");
if(str1==str2)
System.out.println("Equal!");
will print out nothing, because you explicitly stated that you want two new objects.
If you want to avoid complications and unexpected errors, simply never use "==" with strings.

I don't understand this ("string" == "string") example

I found this java code on a java tutorial page:
if ("progress" == evt.getPropertyName())
http://download.oracle.com/javase/tutorial/uiswing/examples/components/index.html
How could this work? I thought we HAVE TO use the equals() method for this situation (string.equals("bla"))? Could we use equals() here too? Would it be better? Any ideas?
Edit: So IF equals() would be better, then I really don't understand why a serious oracle tutorial page didn't use it? Also, I don't understand why it's working because I thought a string is an object. If I say object == object, then that's a big problem.
Yes, equals() would definitely be better and correct. In Java, a pool of string constants is maintained and reused intelligently for performance. So this can work, but it is only guaranteed if evt.getPropertyName() is assured to return constants.
Also, the more correct version would be "progress".equals(evt.getPropertyName()), in case evt.getPropertyName() is null. Note that the implementation of String.equals starts with using == as a first test before doing char-by-char comparison, so performance will not be much affected versus the original code.
Which demo are we looking at?
This explains equals() vs ==
http://www.java-samples.com/showtutorial.php?tutorialid=221
It is important to understand that the equals( ) method and the == operator perform two different operations. As just explained, the equals( ) method compares the characters inside a String object. The == operator compares two object references to see whether they refer to the same instance. The following program shows how two different String objects can contain the same characters, but references to these objects will not compare as equal:
So in your particular example, it is comparing the reference to see if they are the same reference, not to see if the string chars match I believe.
The correct version of this code should be:
if ("progress".equals(evt.getPropertyName()))
This could work because of the way that the JVM handles string constants. Each string constant is intern()ed. So if evt.getPropertyName() is returning a reference to a string constant than using == will work. But it is bad form and in general it will not work.
This only would work if evt.getPropertyName() returns a constant string of value "progress".
With constant string, I mean evaluated at compile-time.
In most cases, when comparing Strings, using equals is best. However, if you know you'll be comparing the exact same String objects (not just two strings that have the same content), or if you're dealing entirely with constant Strings and you really care about performance, using == will be somewhat faster than using equals. You should normally use equals since you normally don't care about performance sufficiently to think about all the other prerequisites for using ==.
In this case, the author of the progress demo should probably have used equals - that code isn't especially performance-critical. However, in this particular case, the code will be dealing entirely with constant strings, so whilst it's probably not the best choice, especially for a demo, it is a valid choice.

java if statement error

It seems to me that this if statement is not working.
I'm new in java, but i know C# and C++ pretty well, but I've never seen such a thing before:
today=edit[0].substring(0,10);
if (today == edit[0].substring(0,10))
{
pars_prog.addView(name_prog[i]);
}
And it doesn't get into the IF function?
Are if statements different in Java (Android)?
When you use == for any object references (whether strings or any other non-primitive type) it simply compares whether the references are equal - i.e. whether they refer to the exact same object, or whether they're both null.
In this case, you want to determine whether the strings are equal - i.e. whether they represent the same sequence of characters. You should use the equals method for that:
if (today.equals(edit[0].substring(0,10)))
However, in general when doing this you should be careful that the target of the equals call is non-null, or you'll get a NullPointerException.
Note that C# is similar - except that the == operator can be overloaded, and is overloaded for string. If the compile-time types of the operands aren't both string, you'll still get reference comparison:
object text1 = new StringBuilder("hello").ToString();
object text2 = new StringBuilder("hello").ToString();
Console.WriteLine(text1 == text2); // False
You are trying to compare strings with ==, which is identity comparison - it will check if the two are the same instance (in the JVM) rather than comparing their contents.
Use today.equals(..) instead.
That said, if appears you are working with dates, so a String is not the best way to handle this. Use Calendar, Date (a bit obsolete) or joda-time DateTime
You have to use the equals method when comparing strings.. Right now you are comparing references and thats why you never enter the if block

Categories

Resources