Reputation: 32081
I have an array of objects that I want to compare to a target object. I want to return the number of objects that exactly match the target object.
Here is my count method:
public int countMatchingGhosts(Ghost target) {
int count=0;
for (int i=0;i<ghosts.length;i++){
if (ghosts[i].equals(target));
count++;
}
return count;
And here is my equals method:
public boolean equals(Ghost other){
if(this == other) return true;
if( !(other instanceof Ghost) ) return false;
Ghost p = (Ghost)other;
if (this.x == p.x && this.y == p.y && this.direction==p.direction && this.color.equals(p.color))
return true;
else
return false;
I run some test code, and I expect 1 matching only, but I get 3 instead. Do you see any errors?
Upvotes: 4
Views: 9260
Reputation: 27256
Just thought I add that while implementing the equals
method in your code, you must also implement (override) the hashCode
method. This is a general contract that you must follow for the best performances.
Below is an excerpt from Joshua Bloch
's book "Effective Java"
Item 9: Always override hashCode when you override equals
A common source of bugs is the failure to override the hashCode method. You
must override hashCode in every class that overrides equals. Failure to do so
will result in a violation of the general contract for Object.hashCode, which will
prevent your class from functioning properly in conjunction with all hash-based
collections, including HashMap,HashSet, and Hashtable.
Here is the contract, copied from the Object specification [JavaSE6]:
• Whenever it is invoked on the same object more than once during an execution
of an application, the hashCode method must consistently return the
same integer, provided no information used in equals comparisons on the
object is modified. This integer need not remain consistent from one execution
of an application to another execution of the same application.
• If two objects are equal according to the equals(Object) method, then calling
the hashCode method on each of the two objects must produce the same
integer result.
And just like Pablo said, if you use anything other than the Object
class in your equals
method signature, you aren't actually overriding the equals
method, and your program won't work as expected.
Take for example this small program that copies a List
to a Set
(which cannot contain duplicates) and prints the new Collection. Try swapping equals(Object obj)
with equals(Item obj)
and see what happens when you run the program. Also, comment out the hashCode()
method and run the program and observe the difference between using it and not.
public class Item {
private String name;
private double price;
private String countryOfProduction;
public Item(String name, double price, String countryOfProduction) {
this.setName(name);
this.setPrice(price);
this.setCountryOfProduction(countryOfProduction);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getCountryOfProduction() {
return countryOfProduction;
}
public void setCountryOfProduction(String countryOfProduction) {
this.countryOfProduction = countryOfProduction;
}
public String toString() {
return "Item Name: " + getName() + "\n" +
"Item Price: N" + getPrice() + "\n" +
"Country of Production: " + getCountryOfProduction() + "\n";
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Item)) {
return false;
}
if(obj == this) {
return true;
}
Item other = (Item)obj;
if(this.getName().equals(other.getName())
&& this.getPrice() == other.getPrice()
&& this.getCountryOfProduction().equals(other.countryOfProduction)) {
return true;
} else {
return false;
}
}
public int hashCode() {
int hash = 3;
hash = 7 * hash + this.getName().hashCode();
hash = 7 * hash + this.getCountryOfProduction().hashCode();
hash = 7 * hash + Double.valueOf(this.getPrice()).hashCode();
return hash;
}
public static void main (String[]args) {
List<Item> items = new ArrayList<>();
items.add(new Item("Baseball bat", 45, "United States"));
items.add(new Item("BLUESEAL Vaseline", 1500, "South Africa"));
items.add(new Item("BLUESEAL Vaseline", 1500, "South Africa"));
Collection<Item> noDups = new HashSet<>(items);
noDups.stream()
.forEach(System.out::println);
}
}
Upvotes: 0
Reputation: 181460
You should override this function:
public boolean equals(Object other) { }
Do note the Object
class being used in method's signature instead of Ghost
. Your can use @Override
annotation to get a compiler error if you are not using method signature correctly.
@Override
public boolean equals(Object other) { }
Having said that, what's probably happening in your code is what the other answer is stating...
Upvotes: 3
Reputation: 455460
There is a ;
at the end of your if
:
if (ghosts[i].equals(target));
^
This makes count++;
happen always irrespective of what your equals
method returns.
Upvotes: 16