java override equals() in custom class - java

I'm trying to Override the vertex variable equals. Currently when vertexList.contains("test") is called, the equals() declared in the vertex class isn't ran. Is there something I'm missing?
The full code can be found on my git hub if you think it's something else, along with a quick test file UI.java. Otherwise I'm out of ideas.
Thanks,
class Data implements Graph
{
java.util.LinkedList<vertex> vertexList = new java.util.LinkedList<vertex>();
class vertex
{
String ID;
java.util.LinkedList<String> links = new java.util.LinkedList<String>();
boolean tracker = false;
public vertex(String it)
{
ID = it;
}
#Override
public boolean equals(Object obj)
{
if (obj.equals(null))
return false;
System.err.println("OBJECT CHECK");
String str = (String) obj;
// return true; //To test if it's being accessed
return str.equals(ID);
}
public String toString()
{
return ID;
}
}
}

Executing vertexList.contains("test") will execute the equals() method of String against your object. You're looking for linkedList.contains(new Vertex("a")); which will execute your equals() method against a target object. Here's the linkedlist impl for contains() where o is the object being searched for.
for (Entry e = header.next; e != header; e = e.next) {
if (o.equals(e.element))
return index;
index++;
}
You should also be checking for a Vertex instead of a String in the equals() method. That is what it is meant for. You should be trying to check if one Vertex equals another.

What are you trying to accomplish in this line?
String str = (String) obj;
If I understood the purpose of your code correctly, I think your equals method should look more like this:
#Override
public boolean equals(Object obj){
if( obj != null && obj.getClass().equals(this.getClass()){
return ((vertex)obj).toString().equals(this.ID)
} else {
return false;
}
}

Related

When trying to overwrite a equals method in Java, it won't compare the values only the object itself?

In this exercise, I need to create a equals() method for a Drink class. Two drinks are the same if they have the same name and same size. I am receiving false from testing the method, even though I'm certain it should be true.
The main code:
public class Drink {
private String name;
private double size;
public Drink(String name, double size)
{
this.name = name;
this.size = size;
}
public String getName()
{
return name;
}
public double getSize()
{
return size;
}
//I tried to stringify the double values
public boolean equals(Drink a, Drink b){
String q = String.valueOf(a.getSize());
String w = String.valueOf(b.getSize());
if(q.equals(w) && a.getName().equals(b.getName())){
return true;
}
else{
return false;
}
}
}
The tester Code:
public class DrinkTester
{
public static void main(String[] args)
{
Drink one = new Drink("Soda", 12);
Drink two = new Drink("Soda", 12);
Drink three = new Drink("Soda", 20);
System.out.println(one.equals(two));
System.out.println(one.equals(three));
}
}
You need to override the equals method, if you use the
#Override annotation you'll see if you're doing it right.
public boolean equals(Object obj) {
return (this == obj);
}
That is the Object one, so yours might for example look like:
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Drink drink = (Drink) obj;
return this.size.equals(drink.size)
&& this.name.equals(drink.name);
}
you'll also have to override your hashCode if you want your code to work optimally.
(And i've only recently noticed that if you use Objects.hash in your overridden hashCode method, your overridden equals method won't get used, the Objects one will get used instead)

Java: add element after an element in the LinkedList

I want to add an element after an element in the list if list already contain that element otherwise I want to add this new element to beginning
of the list.
Somehow below code is not working.
Any suggestions?
Does this approach correct performance wise?
public class HelloWorld
{
public static void main(String[] args) {
LinkedList<Task> l =new LinkedList<Task>();
l.add(new Task("a"));
l.add(new Task("b"));
l.add(new Task("c"));
int index;
if((index = l.lastIndexOf(new Task("a"))) != -1){
l.add(++index, new Task("5"));
}else{
l.addFirst(new Task("6"));
}
System.out.println(l);
}
}
class Task{
String value;
Task(String v){
value = v;
}
public boolean equals(Task t){
return t.value.equals(this.value);
}
public String toString(){
return this.value;
}
}
Output produces: [6,a,b,c]
Expected output: [a,5,b,c]
You are not overriding Object#equals in your Task class.
You need to parametrize it with Object, otherwise it's an overload.
That in turn doesn't allow your new Task("a") to be equal to new Task("a"), as Object.equals in invoked instead, and the references don't match.
This in turn will cripple your lastIndexOf invocation with unexpected results.
Example
#Override
public boolean equals(Object obj) {
// TODO your code, i.e. based on the "value" field
}
If you're using an IDE (which I recommend), you will have features allowing to draft equals (and hashCode) implementations based on your desired properties.
Your equals should look like that.
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Task task = (Task) o;
return value != null ? value.equals(task.value) : task.value == null;
}

What is the best way to compare variables of same class?

I have a class with variables for old data and new data.
Example:
class Person{
String newAddress;
int newMobileNumber;
String newOfficeId;
// many fields like this (atleast 15 fields)
String oldAddress;
int oldMobileNumber;
String oldOfficeId;
// many fields like this (atleast 15 fields)
//getters and setters of all the fields.
}
What I am doing is on click of button storing old data and new data in a table consisting column with the same name as that of fields(for keeping track of old data)
But if all the oldFields are equal to newFields I want to avoid to avoid database operation.
one way of doing this is using many if conditions. like this,
if(oldAddress.equals(newAddress)){
flag = true;
}
if(oldMobileNumber.equals(newMobileNumber)){
flag = true;
}
So I'll need many such if() ,I don't find this solution that good. How can I do this in a better way?
You could also throw away all these double values in your Person class and just create a Person variable that is just used to store the old values. You could just update the old values inside your setter methods. To check if any value changed you could override the equals method and compare the current object to the olvValues variable in your Person class.
Due to this way you will safe yourself some extra work if you are adding variables to your Person class at some point.
this could look something like this.
public class Person{
String address;
int mobileNumber;
String officeId;
// many fields like this (atleast 15 fields)
private Person oldValues;
public Person(String address, int mobileNumber, String officeId) {
this.address = address;
this.mobileNumber = mobileNumber;
this.officeId = officeId;
oldValues = new Person(this);
}
public Person(Person p) {
this.address = p.address;
this.mobileNumber = p.mobileNumber;
this.officeId = p.officeId;
}
// Your method that checks if any value did change.
public void checkIfValuesChanged() {
if(this.equals(oldValues)) {
// Nothing changed
}
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + mobileNumber;
result = prime * result + ((officeId == null) ? 0 : officeId.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if(!(obj instanceof Person)) return false;
Person other = (Person) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (mobileNumber != other.mobileNumber)
return false;
if (officeId == null) {
if (other.officeId != null)
return false;
} else if (!officeId.equals(other.officeId))
return false;
return true;
}
// Your setter methods do save the old values in the oldValues Person object
public void setAddress(String address) {
oldValues.address = this.address;
this.address = address;
}
}
You could use ComparisonChain class from Guava to simplify boilerplate code. In your case in would be something like this:
return ComparisonChain.start()
.compare(newAddress, oldAddress)
.compare(newMobileNumber, oldMobileNumber)
...
.result() == 0;
Though I would definitely recommend you to get rid of copy-paste as suggested by Kevin Esche. Comparison chain would be handy in that case either.
UPD Note that if the members of your class can be null than simple oldAddress.equals(newAddress) won't suffice because of NullPointerException. And if you don't want to depend on Guava you could use Objects#equals method to simplify cumbersome null-checking.
You only need to add all those if statements once, in the overridden Object#equals method for your class.
You can have it automatically drafted for you in most IDEs.
You probably also want to override Object#hashCode along the way.
In Ecplise
Right-click your class
Click Source -> Generate hashCode() and equals()
You then compare two Person instances by just invoking equals.
I suggest to define a class Contact and compare an old contact with a new contact using the standard equals method
import org.junit.Test;
public class MyTest {
#Test
public void myTest() {
Contact oldContact= new Contact("A",1,"A");
Contact newContact= new Contact("A",1,"A");
System.out.println(oldContact.equals(newContact));
}
}
class Contact{
String newAddress;
int newMobileNumber;
String newOfficeId;
public Contact(String newAddress, int newMobileNumber, String newOfficeId) {
super();
this.newAddress = newAddress;
this.newMobileNumber = newMobileNumber;
this.newOfficeId = newOfficeId;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Contact other = (Contact) obj;
if (newAddress == null) {
if (other.newAddress != null)
return false;
} else if (!newAddress.equals(other.newAddress))
return false;
if (newMobileNumber != other.newMobileNumber)
return false;
if (newOfficeId == null) {
if (other.newOfficeId != null)
return false;
} else if (!newOfficeId.equals(other.newOfficeId))
return false;
return true;
}
}
class Person{
Contact newContact;
Contact oldContact;
public Person(Contact newContact, Contact oldContact) {
super();
this.newContact = newContact;
this.oldContact = oldContact;
}
}

Trouble with assertEquals (Java)

I'm trying to make a game of "Rock, papers, scissors". I have tests like these:
#Test
public void rockBeatsScissors() {
assertEquals(rock, rock.vs(scissors));
}
I think it should be enough to write a function Equals, for example:
public class Rock {
Object vs(Scissors s) {
return new Rock();
}
Object vs(Paper p) {
return new Paper();
}
Object vs(Rock r) {
return new Rock();
}
boolean equals(Rock r) {
return true;
}
boolean equals(Paper p) {
return false;
}
boolean equals(Scissors s) {
return false;
}
}
(I know I should add a HashCode function, by the way)
I run the tests and I only get failures. What am I doing wrong?
The equals() method used by assertEquals() would be the one which takes Object as argument. Right now, you haven't overridden the Object#equals() method, but provided your own set of 3 equals method, which wouldn't even be used, and thus the default Object class method is used, which just does reference comparison.
You've to give following implementation:
/**
* Terrible `equals()` method implementation. Just for demonstration purpose.
*/
#Override
public boolean equals(Object obj) {
return obj instanceof Rock;
}

Does Collection's contain method ever return false for an instance added to it?

I was going through Joshua Bloch's online Chapter on "overridding equals() method".
Here's the link.
The following section confuses me,
Reflexivity—The first requirement says merely that an object must be
equal to itself. It is hard to imagine violating this requirement
unintentionally. If you were to violate it and then add an instance of
your class to a collection, the collection’s contains method would
almost certainly say that the collection did not contain the instance
that you just added.
Question - Is it possible for a collection's contain method to return false on an instance added to it?
I tried but the result returned is always true.
To illustrate the point, have this simple class:
class C {
private int i;
public C(int i) { this.i = i; }
}
Now, if you do:
C c1 = new C(1);
C c2 = new C(1);
List<C> l = new ArrayList<C>();
l.add(c1);
l.contains(c2) will return false, since c2.equals(c1) is false, in spite of the fact that both instances have the same constructor arguments.
This is because class C does not override .equals() nor .hashCode().
In general, each time your class is bound to be used in a Collection of any kind, you had better override both of these methods. In this case:
// Note: final class, final member -- that makes this class immutable
final class C {
private final int i;
public C(int i) { this.i = i; }
#Override
public int hashCode() { return i; }
#Override
public boolean equals(Object o)
{
// no object equals null
if (o == null)
return false;
// an object is always equal to itself
if (this == o)
return true;
// immutable class: if the class of the other is not the same,
// objects are not equal
if (getClass() != o.getClass())
return false;
// Both objects are of the same class: check their members
return i == ((C) o).i;
}
}
Question - Is it possible for a collection's contain method to return false on an instance added to it?
Not unless the added object's equals() violates the contract, as the quote from the book explains.
As suggested by #Karthik T, try this with an object whose equals() unconditionally returns false (thereby violating the contract).
Here is a demonstration of a collection's contains method returning false for an object that has just been added to the collection. I took a normal equals and hashCode, generated by Eclipse, and changed the equals method to be non-reflexive. Specifically, it returns false when comparing an object to itself.
import java.util.LinkedList;
import java.util.List;
public class Test {
int someValue;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + someValue;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
// Bad. Non-reflexive. Should return true.
return false;
}
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Test other = (Test) obj;
if (someValue != other.someValue)
return false;
return true;
}
public static void main(String[] args) {
List<Test> myList = new LinkedList<Test>();
Test myObject = new Test();
myList.add(myObject);
System.out.println(myList.contains(myObject));
}
}

Categories