What Is The Difference Between .equals() and ==? - java

I read that .equals() compares the value(s) of objects whereas == compares the references (that is -- the memory location pointed to by the variable). See here: What is the difference between == vs equals() in Java?
But observe the following piece of code:
package main;
public class Playground {
public static void main(String[] args) {
Vertex v1 = new Vertex(1);
Vertex v2 = new Vertex(1);
if(v1==v2){
System.out.println("1");
}
if(v1.equals(v2)){
System.out.println("2");
}
}
}
class Vertex{
public int id;
public Vertex(int id){
this.id = id;
}
}
Output:
(Nothing)
Shouldn't it be printing 2?

You need to implement your own .equals() method for the Vertex class.
By default, you are using the Object.equals method. From the docs, this is what it does:
The equals method for class Object implements the most discriminating
possible equivalence relation on objects; that is, for any non-null
reference values x and y, this method returns true if and only if x
and y refer to the same object (x == y has the value true).
You can do something like this:
#Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (obj.getClass() != getClass()) return false;
Vertex other = (Vertex)obj;
return (this.id == other.id);
}

You need to override the default implementation of equals(). The default implementation is Object#equals():
public boolean equals(Object obj) {
return (this == obj);
}
The overridden version would be something like this:
#Override
public boolean equals(Object obj)
{
if(obj == this) return true;
if(obj == null) return false;
if(obj.getClass() != getClass()) return false;
return ((Vertex) obj).id == this.id;
}

Related

Why equals returns false in my java code?

I do not understand why equals() returns "false" instead of "true" in my code ?
class Location {
private int x, y;
public Location(int x, int y) {
this.x = x;
this.y = y;
}
}
public class App {
public static void main(String[] args) {
Location a = new Location(1, 2); //
Location b = new Location(1, 2); // same values
System.out.println(a.equals(b)); // result : "false"
}
}
How to compare the values of two objects ?
Override the base 'equals' method with this:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Location that = (Location) o;
return x.equals(that.x) &&
y.equals(that.y);
}
Overriding equals() method is like a routine. You can use IDE tools to generate equals() and hashcode() methods.
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Location other = (Location) obj;
if (!getEnclosingInstance().equals(other.getEnclosingInstance()))
return false;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
This method is defined in the Object class so that every Java object inherits it. By default, its implementation compares object memory addresses, so it works the same as the == operator. However, we can override this method in order to define what equality means for our objects.
You Should override override the equals() method for this class so that we can compare two Locations based on their internal details:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Location that = (Location) o;
return x.equals(that.x) &&
y.equals(that.y);
}

Equals method when dealing with inheritance and no instance variables

This is the way we implement equals method in classes.
Class A (Store) with area as instance variable:
#Override
public boolean equals(Object otherObject) {
if (this == otherObject) {
return true;
}
if (otherObject == null || getClass() != otherObject.getClass()) {
return false;
}
Store otherStore = (Store) otherObject;
return area == otherStore.area;
}
Class B (StoreToys) extends Class A (Store) and has no instance variables (dealing with inheritance)
How should i write equals method for this class?
If you don't introduce any new fields in StoreToys you can write the check with instanceof to verify that otherObject can be cast to Store.
#Override
public boolean equals(Object otherObject) {
if (this == otherObject) {
return true;
}
if (!(otherObject instanceof Store)) {
return false;
}
Store otherStore = (Store) otherObject;
return area == otherStore.area;
}

ConcurrentHashMap - Odd behaviour

Can anyone let me know what goes wrong in this piece of code? I'm pulling my hair out!
There isn't any problem if I use HashMap instead of ConcurrentHashMap. The code is compiled with JDK 5.0
public class MapTest {
public Map<DummyKey, DummyValue> testMap = new ConcurrentHashMap<DummyKey, DummyValue>();
public MapTest() {
DummyKey k1 = new DummyKey("A");
DummyValue v1 = new DummyValue("1");
DummyKey k2 = new DummyKey("B");
DummyValue v2 = new DummyValue("2");
testMap.put(k1, v1);
testMap.put(k2, v2);
}
public void printMap() {
for(DummyKey key : testMap.keySet()){
System.out.println(key.getKeyName());
DummyValue val = testMap.get(key);
System.out.println(val.getValue());
}
}
public static void main(String[] args){
MapTest main = new MapTest();
main.printMap();
}
private static class DummyKey {
private String keyName = "";
public DummyKey(String keyName){
this.keyName = keyName;
}
public String getKeyName() {
return keyName;
}
#Override
public int hashCode() {
return keyName.hashCode();
}
#Override
public boolean equals(Object o) {
return keyName.equals(o);
}
}
private static class DummyValue {
private String value = "";
public DummyValue(String value){
this.value = value;
}
public String getValue() {
return value;
}
}
}
This is the output:
B
Exception in thread "main" java.lang.NullPointerException
at test.MapTest.printMap(MapTest.java:27)
at test.MapTest.main(MapTest.java:34)
DummyKey.equals method implementation is incorrect, due to that testMap.get(key) always returns null. Try this
public boolean equals(Object o) {
if (o instanceof DummyKey) {
DummyKey other = (DummyKey) o;
return keyName == null ? other.keyName == null : keyName.equals(other.keyName);
}
return false;
}
hashCode also needs a little change to be consistent with equals
public int hashCode() {
return keyName == null ? 0 : keyName.hashCode();
}
The problem comes from your equals in DummyKey.
When you call DummyValue val = testMap.get(key);, the hashcode function finds a match (both keyname of k1 and key are the same and so are their hashcode). Yet equals returns false because k1.keyname is equal to "A" which is not equal to key itself, which is actually of type DummyValue: you are not comparing properly!
Therefore, you need to modify your equals function:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DummyKey other = (DummyKey) obj;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
return true;
}
Please note that if you change hashCode(), then you must change equals() as well. Otherwise, you will run into problems. If equals() returns true for two items, then their hashCode() value must be equal! The opposite is not required but preferable for better hashing performance. Here is an implementation of equals() and hashCode().
HINT: if you are using eclipse, you can utilize its source generation capability to create the correct hashCode() and equals() method for you. The only thing you need to do is to pick the instance variables that identify the object. To do so in eclipse, while your source code is open, go to the tabs in the top and choose "source", then choose "Generate hashCode() and equals()..."
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((keyName == null) ? 0 : keyName.hashCode());
return result;
}
Override
public boolean equals(Object other) {
if(this == other) return true; //for optimization
if(! other instanceof this) return false; //also covers for when other == null
return this.keyName == null ? other.keyName == null : this.keyName.equals(other.keyName);
}
As others have pointed, the problem lies in the way you override hashcode and equals.
Two options : 1) Just remove the hashcode and equals and it works fine
2) I let eclipse generate the source for hashcode and equals and it works fine. This is what my eclipse belted out for me :
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((keyName == null) ? 0 : keyName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DummyKey other = (DummyKey) obj;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
return true;
}

Why these two Java objects do not equals?

I was make some code and found that objects ar eno equals - it is trivial question but not understand how default equals works.
class A {
String id;
public A(String id) {
this.id = id;
}
public static void main(String args[])
{
A a = new A("1");
A b = new A("1");
System.out.println(a.id);
System.out.println(b.id);
System.out.println(a.equals(b));
}
}
Result is:
1
1
false
But I want to have a.equals(b) == true why it is false?
Your class currently extends only Object class and in Object class equals method looks like this
public boolean equals(Object obj) {
return (this == obj);
}
What you need is to override this method, for example like this
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
A other = (A) obj;
if (id == other.id)
return true;
if (id == null)
return false;
if (other.id == null)
return false;
if (!this.id.equals(other.id))
return false;
return true;
}
Also when you override equals you probably should override hashCode method, but this is not subject of your question. You can read more about it here.
If you don't override equals() on the object, you are comparing two different memory references. So override equals() to compare the id fields.
It overrides Object's equals method by default, it checks the "same object" rather than "same content". If you want to have a.equals(b) == true, you should override it:
#Override
public boolean equals (Object obj) {
if (obj instanceof A) {
A a = (A) obj;
if (id == null) {
return a.id == null;
} else {
return id.equals(a.id);
}
}
return false;
}
----- EDITED -----
you should rewrite an equals() method for your code, as you would a toString() method.

Java: Only check hashCode in equals() of immutable object

I have an immutable object, for example a node in the Cartesian space. The class is immutable, so I cache the hashCode for very fast hashing.
private final int hashCode;
private final double x, y, z;
public Node(final double x, final double y, final double z)
{
this.x = x;
this.y = y;
this.z = z;
this.hashCode = Objects.hashCode(this.x, this.y, this.z);
}
#Override
public boolean equals(final Object obj)
{
if (this == obj) { return true; }
if (obj == null) { return false; }
if (!(obj instanceof Node)) { return false; }
final Node other = (Node) obj;
return Objects.equal(this.x, other.x) && Objects.equal(this.y, other.y) && Objects.equal(this.z, other.z);
}
#Override
public int hashCode()
{
return this.hashCode;
}
Since the hashCode is unique and dependent on all fields of the class AND the class is Immutable, would it be correct to only check Node equality based on the hashCode?
#Override
public boolean equals(final Object obj)
{
if (this == obj) { return true; }
if (obj == null) { return false; }
if (!(obj instanceof Node)) { return false; }
final Node other = (Node) obj;
return this.hashCode == other.hashCode;
}
This passes all Unit Tests I have written about the properties of equals() and hashCode() and their interaction, but perhaps there is something I am missing?
Note: Objects.hashCode() and Objects.equal() are Guava classes helpful for the respective methods.
Nope; that won't work.
You have 232 possible hashcodes and 2192 possible values.
No, but..
I guess you could check the hashcode to see whether objects are not equal and gain some performance there:
public boolean equals(final Object obj) {
if (this == obj) { return true; }
if (!(obj instanceof Node)) { return false; }
final Node other = (Node) obj;
if (this.hashCode != other.hashCode) {
return false; // If hashcodes differ, we're sure the objects are not equal
}
// remainder of the actual equals implementation
}
Of course this will only improve performance in case most of your comparisons yield false. In case of equal objects, this will bring a performance penalty. In your example (comparing just three values), I wouldn't recommend this.

Categories

Resources