pieces instance is a List that contains class Piece. Piece object contains two instance variables that resemble coordinate int x and int y. However, when I tried these methods, the second method does not return true if the parameter piece is already inside the pieces object. I have generated an equal method on the class Piece. not sure why the second method does not work.
public boolean alreadyContainsCoordinate1(Piece piece) {
for (int i = 0; i < getLength(); i++) {
if (pieces.get(i).getX() == piece.getX() && pieces.get(i).getY() == piece.getY()) {
return true;
}
}
return false;
}
public boolean alreadyContainsThisCoordinate2(Piece piece) {
for (Piece body : pieces) {
if (body.equals(piece)) {
return true;
}
}
return false;
}
Your second alreadyContainsThisCoordinate2() method is probably using the default equals() method for objects, which compares references, not the contents of your particular object. You may try to override equals as follows:
#Override
public boolean equals(Object o) {
if (!(o instanceof Piece)) {
return false;
}
Piece p = (Piece)o;
return this.getX() == p.getX() && this.getY() == p.getY();
}
Related
According to this answer, roughly, if we had a Classroom object array of student objects, class[index] != student1. I believe this is the mistake I am making in implementing my equals method to compare the array[index] object to another object. I believed the array[index] and the object I am comparing against to be the same.
The code below shows my getNumStudents method in which I try to count the number of times a student id shows up in a class. ID represents brand shoes he or she likes (practice exercise out of lecture). This method is in my classroom object class which implements an interface.
#Override
public int getNumStudents(T anEntry) {
int count = 0;
for (int index = 0; index < numberOfEntries; index++) {
if (roster[index].equals(anEntry)) )
{
counter++;
}
}
return count;
}
My equals method is as such and is implemented in the student class:
public boolean equals(Student student) {
if (this == student)
{
return true;
}
if (student == null)
{
return false;
}
if (this.getID() != student.getID())
{
return false;
}
return true;
}
I don't know if I properly did the hashCode override but here it is (in Student class):
#Override
public int hashCode() {
int result = 17;
result = 31 * result + studentID;
return result;
}
I've narrowed down where the bug is to most likely here:
if (roster[index].equals(anEntry)) )
specifically
roster[index].equals(anEntry))
What should I call or how should I adjust my getNumStudents(T anEntry) method to properly return the number of students with a certain ID (representing a shoe type) within a Classroom object array?
Your equals signature is wrong.
The correct signature of equals method must be as follows.
public boolean equals(Object other)
Then inside the method you should check if it is of comparable type and if you really need it to be of type Student, you have to check for this and return false otherwise.
In your case that would be a minimal change required for your implementation:
public boolean equals(Object other)
{
if (this == other)
{
return true;
}
// This also works if `other` is `null`
if (!(other instanceof Student))
{
return false;
}
// Now we cast it to `Student`
final Student student = (Student) other;
if (this.getID() != student.getID())
{
return false;
}
return true;
}
This question already has answers here:
How the equals() method works
(8 answers)
What issues should be considered when overriding equals and hashCode in Java?
(11 answers)
Closed 5 years ago.
Consider:
class Dog{
int height;
int weight;
String name;
}
public class DogTest {
public static void main(String[] args) {
Dog one = new Dog();
one.height=4;
one.name="fudo";
one.weight =2;
Dog two = new Dog();
two.height=4;
two.name="fudo";
two.weight =2;
if (one.equals(two)){
System.out.println("True");
}
else{
System.out.println("False");
}
}
}
Why does this output "False"? If it is by default in Java that "all objects are not equal even if they have same values" then how can I "persuade" Java that these two objects actually are equal?
Okay, even if two dogs have same name, height, weight one could be Dalmatian and the other one pit bull, and even if they are the same "race", in nature, they can always be different from one another.
PS: I understand that by saying if (one==two) {} we are comparing if they both refer to the same object on the heap, .equals on string's compares if they have same characters in the same order.
The equals method by default says "Is this the same object in memory?" unless you override it.
You didn't override it.
The behavior didn't change.
You'll want to add a new method like this
public boolean equals(Object o) {
if(o instanceof Dog) {
Dog d = (Dog)(o);
Dog t = this;
return t.height == d.height && t.weight == d.weight && t.name.equals(d.name);
}
return false;
}
Stephan brings up a good point - never, ever, ever implment equals without hashCode. Always use the same fields in both.
public int hashCode() {
int hash = name.hashCode();
hash = hash * 31 + weight;
hash = hash * 31 + height;
return hash;
}
You have to override your equals method in your Dog class. If not you are just comparing if those objects are the same instance in memory.
Here is an implementation of how to do this:
class Dog{
int height;
int weight;
String name;
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Dog)) return false;
Dog dog = (Dog) o;
if (height != dog.height) return false;
if (weight != dog.weight) return false;
return name != null ? name.equals(dog.name) : dog.name == null;
}
}
Any IDE allows you to generate a hashcode and equals in an automatic way as getters and setters.
In your case without hashcode and equals, you will get false, because the objects cannot being at the same memory location.
Your (working) example below:
class Dog{
int height;
int weight;
String name;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + height;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + weight;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) obj;
if (height != other.height)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (weight != other.weight)
return false;
return true;
}
public static void main(String[] args) {
Dog one = new Dog();
one.height=4;
one.name="fudo";
one.weight =2;
Dog two = new Dog();
two.height=4;
two.name="fudo";
two.weight =2;
if (one.equals(two)){
System.out.println("True");
}
else{
System.out.println("False");
}
}
}
Result:
To generate hashCode and equals in automatic way in Eclipse:
Right click in your class and:
public class Glasses {
String manufacturer;
int price;
String type;
Glasses() {
}
Glasses(String prd, int pr) {
manufacturer = prd;
price = pr;
}
Glasses(String prd, int pr, String t) {
manufacturer = prd;
price = pr;
type = t;
}
public static void Compare() {
}
}
this is my code and i want to compare 2 glasses like i initialise an object glasses1(ray-ban,200,squared) and glasses2(china,100,rounded) and I want them to be compared. How can i do that?
You can overwrite the method equals(Object) from class Object which returns the boolean if they are equal (you can define by yourself within this method what needs to be equal to define these instances as equal).
If you want the classes to be sortable for sorted map then you can implement the interface Comparable and the method int compare(Object).
For instance:
#Override
public int compareTo(Glasses other) {
if (equals(other)) {
return 0;
} else {
//FIXME: when is a Glasses object smaller then an other Glasses object??
return 0;
}
}
#Override
public boolean equals(Object o) {
boolean equal = false;
if (o instanceof Glasses) {
Glasses other = (Glasses) o;
equal = true;
equal &= (manufacturer == null && other.manufacturer == null) || (manufacturer != null && manufacturer.equals(other.manufacturer));
equal &= price == other.price;
equal &= (type == null && other.type == null) || (type != null && type.equals(other.type));
}
return equal;
}
The implementation of the compare method is buggy because I don't know your logic when a Glasses object is 'smaller' or 'bigger' than an other Glasses object. Maybe you just need the equals method?
Addition:
The equals method can be made a little bit smaller but maybe a little bit harder to understand (depends on the fact if you know the handling of the "?"-operator):
#Override
public boolean equals(Object o) {
boolean equal = false;
if (o instanceof Glasses) {
Glasses other = (Glasses) o;
equal = true;
equal &= manufacturer == null ? other.manufacturer == null : manufacturer.equals(other.manufacturer);
equal &= price == other.price;
equal &= type == null ? other.type == null : type.equals(other.type);
}
return equal;
}
For my equals method that checks to see if two arrays are equal, does the first method "equals" actually check if the two arrays are equal or only tests the memory addresses? Or should I include both?
public boolean equals(Object otherObject)
{
if (otherObject == null)
{
return false;
}
else if (getClass() != otherObject.getClass())
{
return false;
}
else
{
RegressionModel otherRegressionModel = (RegressionModel)otherObject;
return (xValues == (otherRegressionModel.xValues) && yValues == (otherRegressionModel.yValues));
}
}
OR
public static boolean equalArrays(double[] x, double[] y)
{
if(x.length != y.length)
{
return false;
}
else
{
for(int index = 0; index < x.length; index++)
{
if (x[index] != y[index])
{
return false;
}
}
return true;
}
}
the =/!= operator compares arrays based upon their reference, and not their content. Clearly two arrays may have the same elements, except they are still two distinct objects that are created in the memory. The arrays are two references. Therefore your second method should be applied, because it compares the actual elements inside the two arrays. Also you don't need your else statement.
public static boolean equalArrays(double[] x, double[] y)
{
if(x.length != y.length)
{
return false;
}
for (int index = 0; index < x.length; index++)
{
if (x[index] != y[index])
{
return false;
}
}
return true;
}
One more check can also be applied on first equals method where it can see both array has an same reference or not. Then other comparison can be done. In second method it always check the element of an array, even if both an reference of same array. so in terms of performance it will take time.
public boolean equals(Object otherObject)
{
if (otherObject == null)
{
return false;
}
else if (getClass() != otherObject.getClass())
{
return false;
} else if (this != otherObject)
return false;
}
else
{
RegressionModel otherRegressionModel = (RegressionModel)otherObject;
return (xValues == (otherRegressionModel.xValues) && yValues == (otherRegressionModel.yValues));
}
}
Adding to #Henry's answer, before comparing lengths of the two given arrays you should make sure that neither of them are null so that you don't get a NullPointerException.
You might also want to compare the references of the arrays before looping through their elements.
Something like this:
public static boolean equalArrays(double[] x, double[] y)
{
if (x == null || y == null || x.length != y.length)
{
//NOTE: That if both x and y are null we return false despite the fact that you could argue that they are equal
return false;
}
if (x == y)
{
return true;
}
for (int index = 0; index < x.length; index++)
{
if (x[index] != y[index])
{
return false;
}
}
return true;
}
I'm trying to use HashSet to store objects of a class that I created, but apparently the same objects seem to have two different hashes, which is why the contains method does not realize that the object is already in the HashSet. This leads to my program running out of heap memory.
I don't think I'm doing anything wrong, but I wanted a second opinion anyway. I've done similar operations before which all worked fine, which makes this particularly annoying. I'd appreciate any help.
Here's my code
move1 = new Move(t,s);
if(move1.hashCode()==new Move(t,s).hashCode())
System.out.println("match");
move2 = new Move(s,t);
moves.add(move1);
moves.add(move2);
if(moves.contains(new Move(t,s)))
System.out.println("match found");
Here's the Move class:
public class Move {
private int move1;
private int move2;
Move(int m1, int m2)
{
move1 = m1;
move2 = m2;
}
public String toString()
{
return String.valueOf(move1)+" "+String.valueOf(move2);
}
}
Here's the output I get
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.addEntry(HashMap.java:797)
at java.util.HashMap.put(HashMap.java:431)
at java.util.HashSet.add(HashSet.java:194)
at makeMove.<init>(makeMove.java:33)
You need to override the Object#hashCode() method in the Move class to let it return the same hashCode() value for the state of the Move instance. Don't forget to override Object#equals() as well.
See also:
Overriding equals and hashCode in Java
Hint: if you're using an IDE like Eclipse, you can also just autogenerate them. Rightclick somewhere the Move class, choose Source > Generate hashCode() and equals(). Here is how it look like then:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + move1;
result = prime * result + move2;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Move other = (Move) obj;
if (move1 != other.move1)
return false;
if (move2 != other.move2)
return false;
return true;
}
HashSet will determine equality based on calling hashCode() and equals(). You have not implemented these, so you'll inherite them from Object. The hashCode and equals methods of Object is just based on whether the references are equal.
That's why if(move1.hashCode()==new Move(t,s).hashCode()) is false. move1 is a different instance than the instance created by calling new Move(t,s).hashCode()
You'll need to implement hashCode and equals in your Move class.
e.g.(though perhaps non-optimal, and you might want a null safe equals - have your IDE generate them if it can)
public int hashCode() {
return move1 ^ move2 +;
}
public boolean equals(Object o) {
if(!other instanceof Move)
return false;
Move other = (Move)o;
return other.move1 == move1 && other.move2 == move2;
}
You have to override equals() and hashCode().
This may be an option.
import static java.lang.System.out;
public class Move {
private int move1;
private int move2;
Move(int m1, int m2) {
move1 = m1;
move2 = m2;
}
public String toString() {
return String.valueOf(move1)+" "+String.valueOf(move2);
}
public int hashCode() {
return move1 * 31 + move2 * 31;
}
public boolean equals( Object other ) {
if( this == other ) { return true; }
if( other instanceof Move ) {
Move m2 = ( Move ) other;
return this.move1 == m2.move1 && this.move2 == m2.move2;
}
return false;
}
public static void main( String [] args ) {
out.println( new Move(2,3).equals( new Move(2,3)));
out.println( new Move(1,1).hashCode() == new Move(1,1).hashCode() );
}
}
You have to define if the order of the move is relevant ( 1,2 isequals to 2,1 or not )
For more information:
What issues should be considered when overriding equals and hashCode in Java?