Java string comparison is not working when concatenated with number - java

My question to java folks is, when I am comparing two strings
imageName=new String[20];
....
imageName[1]="img1";
imageName[2]="img1";
if(imageName[1]==imageName[2])
{
//// codes
}
it works perfectly, but when I am making the string through number concatenation it's not working
imageName=new String[20];
int j=1,k=1;
imageName[1]="img"+j;
imageName[2]="img"+k;
if(imageName[1].toString()==imageName[2].toString())
{
//// codes
}
it's not working though the values of j and k are the same
Thanks in advance for your solution

You should use String.equals when comparing two Strings:
if (imageName[1].equals(imageName[2])

You shouldn't compare strings with ==, but instead use the .equals method: imageName[1].equals(imageName[2]).
== compares the pointers for equality, so it'll be true if both variables represent the exact same instance in memory. In the first case, it's the case because Java pools String literals for performance. But in your second case, you're getting two distinct heap-allocated objects, which, despite their content is identical, are two distinct objects nonetheless.

You are comparing whether the two String are exactly the same object.
What you intended was to compare their contents. I suggest you use .equals instead.

Never, ever, use "==" to compare Strings in Java. Use the equals() method. The == operator checks to see if two String variables are referring to the same location in memory, while the equals() method checks whether two separate String objects contain the same characters. It's this second definition that makes sense here: your String concatenation is creating separate String objects, but we still want to consider them as "equal".

The correct way to compare strings is using equals() method
So, Please change your code as below,
if (imageName[1].equals(imageName[2])
And please consider to do a research in SO before posting, as the questions like this have been answered many times before.

== is a reference comparison. That is, you're determining if the two objects are, in fact, the same object. If you use equals() then that method comparses the contents of the string i.e. do those objects have the same contents (you'll appreciate there is a subtle difference here)
Your first scenario works since the compiler is clever enough to realise that you have the same string twice. i.e. it looks at:
imageName[1]="img1";
imageName[2]="img1";
and determines that your array elements can point to the same object. In your second scenario, that's no longer true.
imageName[1]="img"+j;
imageName[2]="img"+k;
The compiler can't reliably determine that these could be the same string object (quite correctly, too).
So (generally speaking) you should use equals() to compare Strings. You can use the reference equality (it's faster since it comparse the references rather than the string contents), but you have to be absolutely sure about what you're doing (perhaps you're using String.intern() - but there are disadvantages there)

To compare two Strings you better use equals() method
if(imageName[1].equals(imageName[2]))
{
//// codes
}

Related

(Java) Comparing values of two variables in if-statement but can't use `.equals()`

(Heads up, I've never written a proper program before so bear with me)
I'm trying to write an if-statement that compares the VALUES of the position fields of two instances (which literally returns the integer "position"). Problem is, they are private fields in different classes so I cannot access them directly. Instead, I made methods in each class which return the variable.
Now in my if-statement, this is the condition that is to be true/false:
if (enemy1.getPosition() = player.getGun1Position())
Now the problem is, if I use = the machine assumes I'm trying to assign a value to the position of enemy1 and I've been researching to find that == compares the memory location rather than the value of the two fields.
I have also read that
.equals()
can be used but I'm assuming it can't be used here because
enemy1.getPosition().equals(player.getGun1Position())
gives an error when I try it.
NOTE: I cannot change the fields to public because this is for an assignment and the fields need to be private.
Any help would be appreciated :)
I'll briefly walk you through comparisons.
1) Primitives just need == operator to match values except, String values which are not permitives will compare their memory locations. for strings use .equals().
2) For objects of primitives like Integer,Double still compares the memory location with == operator. You need to invoke their .equals to compare them. If you have your own class you need to define your own version of equals method, means overriding.
Have you tried == yet?
If it is truly retiring a integer, than == is the way to go.
You can not call functions on primitives like int, char, double, float, long,short,byte. So there is no .equals() to call.
In the case of classes, you need to call .equals(), because a class variable is like a pointer, so you don't want to compare two pointers to each other with ==. However, primitive variables just contain their "values", so == is perfect for comparing values.
If you haven't tried this, you need to be more experimental with your coding.
Just test it.
System.out.println(enemy1.getPosition()+" == "+ player.getGun1Position()+": "+(enemy1.getPosition()==player.getGun1Position()));
if(enemy1.getPosition()==player.getGun1Position())
{
//blah
}
If that doesn't work, then you are not returning an int primitive, but instead an Integer object (note the capital I).
In this case,
if(enemy1.getPosition().equals(player.getGun1Position()))
OR
if(enemy1.getPosition().getIntValue()==player.getGun1Position().getIntValue()))
Should work fine.

Why assertEquals(new int[]{1}, new int[]{1}) results in failure?

I was testing my shuffling class and came across one issue I cannot understand. Why does the following assert statement:
assertEquals(new int[]{1}, new int[]{1});
results in an AssertionError? Naturally, the correct answer is "because they are not equal!", but could someone explain me why? And how to test a method, for which I would like the two such objects to be equal?
but could someone explain me why
Sure - arrays don't override equals, therefore they inherit the behaviour from Object, where any two distinct objects are non-equal.
It's even simpler than the version you showed if you use a 0-element array:
System.out.println(new int[0].equals(new int[0])); // false
That's why when checking for equality in non-test code you use Arrays.equals, and when checking for equality in test code you use a dedicated assertXyz method (where the exact method depends on the version of JUnit etc).
assertEquals calls the equals object in one of the objects to compare it with the other.
Arrays need to be compared using Arrays.equals() if you want a full comparison of the two arrays, otherwise unfortunately they just use the Object equals method.
See also: equals vs Arrays.equals in Java
Because you create 2 different objects and they point to different locations in the memory.
When comparing objects, you use the equals() method inherited from the class Object. Now, if you don't override the method in your class, you will have the default behaviour which is the comparison of objects address. In the code you create 2 arrays, but even though their content is the same, not the content is tested for being equal, but the objects reference by using the inherited equals() method from Object class.

HashMap (Java) giving wrong results

I have created a hash map in which each entry corresponds to 3 values
Key object values ( which are two in number)
I have created a class ,whose object i create and store the results in a hash map
This is my code below in which i compare my incoming data with the previous values in the hash map.If the same data comes then i just increment the counter of that data. I have taken the print statements in the the for loop . though the two strings match but still my code never comes in the if loop for increment the counter.Why?
for(i=1;i<=hMap.size();i++)
{
String skey = Integer.toString(i);
if(hMap.get(skey).olddata==comingdata)
{
hMap.get(skey).counter= hMap.get(skey).counter+1;
}
}
You haven't given nearly enough information about the types involved, but, but I strongly suspect that this is the problem:
if(hMap.get(skey).olddata==comingdata)
That will be comparing references, rather than for equality, if olddata and comingdata are references of some kind. (EDIT: By the sounds of it, they're string references.)
My guess is that you want:
String skey = Integer.toString(i);
if(hMap.get(skey).olddata.equals(comingdata))
{
hMap.get(skey).counter= hMap.get(skey).counter+1;
}
Or rather more efficiently, avoiding pointless lookups:
WhateverType value = hMap.get(Integer.toString(i));
if (value.olddata.equals(comingdata))
{
value.counter++;
}
I'd also suggest that if you're always going to look up by an integer, why not use an Integer key instead of always converting the integer into a string?
Additionally, it's worth following Java naming conventions, and you should make your fields private if they're not already.
If none of this helps, please post more code. The chances of the problem being in HashMap rather than in your code are incredibly small.
It's not clear the type of olddata, but maybe you should compare the values using equals():
if (hMap.get(skey).olddata.equals(comingdata))
In Java, == is used for either comparing primitive data types for equality or comparing object types for identity. If you need to compare two object types for equality, then you must use the equals() method, which is defined for all objects since it's inherited from the Object class, being aware that you also must override equals() and hashCode() in your class, providing implementations meaningful for that class.
You don't compare objects with == in Java unless you're trying to see if they have the same reference value.
if (hMap.get(skey).olddata.equals(comingdata)) {
...
You also shouldn't be exposing olddata like that; it should be available via a getter; e.g. getOldData()
It should be
if(hMap.get(skey).olddata.equals(comingdata))
Do you actually mean comingdata.equals(hMap.get(skey).olddata)? Furthermore be aware that equals(Object) and hashCode() must be correclty implemented.

Java Equality not Behaving as Expected

I'm currently working on an android application that uses a subclass of SimpleListAdapter to bind a ListActivity. The list that the Adapter binds to is of type List<HashMap<String, Object>>.
I have to following If statement in the list Adapter...
if (dataRow.get("HasLineup1").toString()) == "0")
This never evaluates to true for me, even when the Eclipse debugger says that dataRow.get("HasLineup1").toString() is equal to "0" in the inspection window.
The list of data is populated from an XML source with the line
Game.put("HasLineup1", attributes.getNamedItem("home_lineup").getNodeValue());
I managed to work around the issue by changing the If statement to
if (Integer.parseInt(dataRow.get("HasLineup1").toString()) == 0)
Can someone explain to me why the first If statement I used wasn't working? Java isn't my native language, but I can't for the life of me figure out what I'm doing wrong based on my .Net background.
The == operator compares the instance memory location for non-primitive types therefore this fails unless the two sides of the operand are the same instance. Whenever dealing with non-primitive types, use equals instead of ==.
If you're using string you should do it with equals method.
if (dataRow.get("HasLineup1").toString())equals("0"))
The equality operator == will do the following, based on what you're comparing:
Two primitive types (e.g. int, char, ...): check if their values are the same.
Two non-primitive types (class instances): check if the compared references point to the same object in memory.
In other words, for non-primitives == doesn't imply semantics. You'll want the equals method for that. It's defined on Object so it'll always be available. But its semantics are determine by how (and if) a specific class decides to override this method.
For String, it's a character-by-character comparison with the argument of the method.
Here is a link with references about the differences between == and equals. == compares references, while equals() compares the values.
http://leepoint.net/notes-java/data/expressions/22compareobjects.html
Use
if (dataRow.get("HasLineup1").toString()).equals("0"))
== (double equals) only compares the objects to see if they point to the same place in memory. the equals method actually compares the characters in the two strings to one another.
You must use method "equals" or call .internal() on both strings before using "==".

Java: If I overwrite the .equals method, can I still test for reference equality with ==?

I have the following situation: I need to sort trees based by height, so I made the Tree's comparable using the height attribute. However, I was also told to overwrite the equals and hashCode methods to avoid unpredictable behaviour.
Still, sometimes I may want to compare the references of the roots or something along those lines using ==. Is that still possible or does the == comparison call the equals method?
equals() is meant to compare an object with rules set by the programmer. In your example you compare your trees by height, so you'll write equals() so it compares heights.
==, as you said, compares references. These aren't touched neither by equals() nor by hashCode(). So you won't change its behaviour.
Yes, == will not call hashCode or equals. You can still test for reference equality like this.
== does not call equals. So it's still find for identity checks.
As many implementations of equals start with this == other check you would get a literal StackOverflow if it were calling equals behind the scenes.
I think that a bigger question here is whether it is appropriate to implement comparable on these objects. It may be more appropriate to use a Comparator for the operations that work on height, and not embed ordinal computation in the class itself.
My general philosophy on this is to only implement Comparable if there is a truly natural ordering for the object. In the case of a tree node, is height the only way that anyone could ever want to sort? Maybe this is a private class, and the answer is 'yes'. But even then, creating a Comparator isn't that much extra work, and it leaves things flexible in case you decide you want to make that tree node a protected or public class some day.
== tests referential equality. It will not call equals.
Overriding the equals() method will have NO effect on the == operator.
== is used to test if 2 references point to the same object.
equals() method "meaningfully" compares 2 objects.
It is important to realize the implication of the work "meaningful" here. Equality is easier to understand when you are comparing, for instance, 2 Strings or 2 integers. This is why, the equals() method - inherited from the Object class - is already overridden by the String and Wrapper classes (Integer, Float, etc). However, what if you are comparing 2 objects of type Song. Here, equality can be established on the basis of
1) Artist name
2) Song name
3) or some other criterion
Therefore, you have to override the equals() method to "explicitly" determine "when" 2 Song objects are considered equal.
The "unpredictable behavior" you mentioned in your question relates to objects like the one above (Song) behave when dealing with Collections like Map. You SHOULD NOT use these objects in a map until you override both the equals() and hashcode() method. The reason being how hashmap search and indexing works. Refer the JavaDoc for the specifc rules. What you should remember is:
If 2 objects are meaningfully equal, their hashcode should return the same value. However, it is not necessary for 2 objects to be equal, if they return the same hashcode. Again, Java doesn't enforce any rules regarding this. It is your responsibility to implement the equals() and hashcode() methods correctly.

Categories

Resources