Reflexive property in java Equals method - java

I am reading up on how to properly override the equals in Java, and ran into this sample. My first thought is that it would pass the reflexive property, but apparently it doesn't.
It basically returns false because of this line: if(this != tc) return true;
But isn't checking the same instance tc1, so tc1.equals(tc1), wouldn't it be passing a copy of the reference tc1, meaning they both are pointing to same TestClass object, and thus this and tc1 are essentially pointing to same object?
class TestClass {
int someVar;
TestClass(int i) {
someVar=i;
}
public boolean equals(Object tc) {
if (tc instanceof TestClass && this.someVar == ((TestClass) tc).someVar) {
if (this != tc) {
return true;
} else {
return false;
}
}
return false;
}
public int hashCode() {
return 1;
}
}
public class HashDemo {
public static void main(String []args) {
TestClass tc1 = new TestClass(20);
System.out.println(tc1.equals(tc1));
}
}

I think you have some of your if statements turned around.
Conventional equals method here would look something like this.
public boolean equals(Object that){
if (this == that) {
return true;
}
if (that instanceof TestClass && this.someVar == ((TestClass) that).someVar ) {
return true;
}
return false;
}

This is clearly not the right way to override the equals method, but it allows you to point the difference between "==" and "equals" on Objects
The egality between two references is done with the " == " operator.
The equals method is used to test the egality by values, that's why you can override it depending on your functionnal needs.
Regarding your code :
tc1 == tc1 -> TRUE
tc1.equals(tc1) -> FALSE

Related

Using the boolean object equals() in my implemented equals()

So I am doing a junit test in Java.
I am supposed to test two concrete types
public class BoolValue implements Value{
private boolean item;
//the Constructor
public BoolValue(boolean data){
item = data;
}
//checks to see if the current object is of the same type as the parameter
public boolean equals(Value v){
boolean result = false;
if (v instanceof BoolValue) {
if(this == v)
result = true;
}
return result; //true if equal
}
// returns current state string
public String toString(){
return " "+item;
}
}
This is the test case in my test file
#Test
public void testBoolean(){
BoolValue value = new BoolValue(true);
BoolValue value2 = new BoolValue(true);
assertEquals(true, value.equals(value2));
}
It returns false instead of the expected true
In the equals method, I want to compare two boolean types but I can't use the java.object equals() because the program reads it as the class equals() so its recursive.
How do I call the java.object equals() for comparing boolean types. Also, am I going about this the right way
if (v instanceof BoolValue) {
if(this == v)
result = true;
}
You cannot use == when you want new BoolValue(true).equals(new BoolValue(true)). You need to compare the two item inside them.
Also, you need to accept Object to get a "proper" equals method.
#Override
public boolean equals(Object v){
return (v instanceof BoolValue && ((BoolValue)v).item == this.item);
}
And when you override equals, you also need to override hashCode.
#Override
public int hashCode(){ return item ? 0 : 1; }
Finally (unless you intend to make these "values" mutable), since there are only two possible values, you should make the constructor private and provide the two values as static fields instead (you could also use an enum).
public class BoolValue implements Value {
private final boolean item;
private BoolValue(boolean v){
this.item = v;
}
public static final BoolValue TRUE = new BoolValue(true);
public static final BoolValue FALSE = new BoolValue(false);
public static BoolValue valueOf(boolean x){
return x ? TRUE : FALSE;
}
}

How to test if a list of objects contains an object that contains a particular string as an attribute?

I'm trying to figure out how to test if a list of objects contains an object that contains a particular string as an attribute.
So here Is my list of objects
ArrayList<mObject> objectsList;
And here is my mObject class
public class mObject {
String x = "True";
}
And here I try to make some kind of test
if(ObjectsList.contains(object.x == "True")){
return true;
} else {
return false;
}
I know the syntax is kind of ridiculous, but how can I make it technically correct?
For previuos versions of Java 8:
public class MObject {
private String x = "True";
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
}
You can iterate over the list:
ArrayList<MObject> objectsList; //Init your object list.
for(MObject object : objectsList) {
if(object.getX().equals("True")) {
return true;
} else {
return false;
}
}
Java 8:
List<mObject> list = ObjectsList.stream().filter(obj -> obj.x.equals( "True")).collect(Collectors.toList()).;
if (list.size() != 1) {
return false;
} else {
return true;
}
and, please, observe java naming conventions
for Java 8 you can use
objectsList.stream().anyMatch(myObject -> myObject.x.equals("True"));
please look at the code standards about naming variables (lowercase start and camel case) and classes (uppercase start)
PS: As your variable is a string with "True" value - are you sure not wanting to have a boolean?
I override equals() method to be able to use .contians() because it comparing objects using equals(),as your List is List<mObject> (List of custom object) so i had to override the .equals() to be able to use .contains() probably
public class mObject {
private String x = "True";
public String getX(){
return x;
}
public void setX(String x){
this.x=x;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final mObject other = (ttt) obj;
if (!Objects.equals(this.x, other.x)) {
return false;
}
return true;
}
}
To make your test :-
if(ObjectsList.contains(object) && object.getX().equals("True")){
return true;
} else {
return false;
}
Please see the difference between == and .equals() when comparing string
from this and that link

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

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;
}

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.

Categories

Resources