I am writing a class called Coord. I have created a constructor:
public final int r,c;
public Coord (int r, int c){
this.r = r;
this.c = c;
}
I also did another two methods
//Creates and returns a new Coord value with the same row/column
public Coord copy(){
Coord copy = new Coord (r,c);
return copy;
}
//Given another object, is it also a Coord with the same row and column values?
public boolean equals(Object o){
return this==o; //this may be incorrect.
}
Now I can not pass some test cases as following:
Coord c = new Coord (5,10);
#Test (timeout=2000) public void coord() {
assertEquals(c, c.copy());
assertEquals(c, c);
assertFalse(c.equals(new Coord (2,3))); // #(5,10) != #(2,3).
assertFalse(c.equals("hello")); // must work for non-Coords.
}
I think the problem may arise from my boolean equals method, but I have tried a lot I still cannot pass the test. Is there a deep equal issue here? Can someone help me?
Is there a deep equal issue here?
Well yes, your equals method just checks whether the value passed to it is the same reference. Your comment says what you want to do:
//Given another object, is it also a Coord with the same row and column values?
So that's what you need to implement:
#Override public boolean equals(Object o) {
if (o == null) {
return false;
}
if (o.getClass() != getClass()) {
return false;
}
Coord other = (Coord) o;
return other.r == r && other.c == c;
}
I'd also encourage you to make the class final (in which case you can use instanceof instead of calling getClass()) and you need to implement hashCode() to be consistent with equals too. For example:
#Override public int hashCode() {
int hash = 23;
hash = hash * 31 + r;
hash = hash * 31 + c;
return hash;
}
Related
I have a Java class containing a 2D int array. I want to implement the hashCode() method so that different objects can be compared using their attributes and not reference. This is what I tried:
public int hashCode() {
int hash = 0;
for(int i=0; i<getMatrix().length; i++) {
hash =+ Arrays.hashCode(getMatrix()[i]);
}
return hash;
}
I also tried using deepHashCode() but didn't work. My problem is that when the get() method of a HashMap object is used, even though both the object have the same matrix, the get() method does not work properly.
EDIT:
Implementation of equals method
public boolean equals(Object o) {
boolean sameBoard = false;
if(o != null && o instanceof Node) {
Node node = (Node) o;
int[][] board1 = this.getMatrix();
int[][] board2 = node.getMatrix();
return Arrays.deepEquals(board1, board2);
}
return sameBoard;
}
I'm new to Java. I'm writing a 2d game and I've decided to use a HashMap to store my map data because I need to support negative indices for my map coordinates. This is because the size of the map can grow during the game.
I have written a custom Pair class that stores final x and y values. I am using this Pair object as my key for my HashMap. My values are instances of a custom Cell class.
I have declared my HashMap as follows:
HashMap<Pair, Cell> tiles = new HashMap<Pair, Cell>();
Next, I add entries to my map using:
tiles.put(new Pair(0,0), new Cell());
0,0 is obviously my unique x,y coordinate for this cell.
How do I access the fields and methods of Cell using the .get() method of HashMap, specific to an individual Pair? Such as Pair(0,0) or Pair(0,1). If the key was simply a string or an int, I would have no problem. I just can't figure out how to format my key for an object with a specific coordinate.
You need to override the equals and hashCode method of the Pair class. Right now, if you have two instances of Pair as such:
Pair p1 = new Pair(0,0);
Pair p2 = new Pair(0,0);
These two instances in your program would not be seen as equal, and hence if you said:
tiles.put(p1, XXX);
tiles.put(p2, YYY);
the behavior would be such that your map would have two distinct keys, with two distinct values - where I believe what you would want is one key, with the last value YYY after these statements execute.
After implementing hashCode and equals, you could write a static helper method that instantiates a new Pair with some given coordinates, and performs a map lookup:
static Cell lookup(int x, int y) {
return tiles.get(new Pair(x, y));
}
Here's a basic Pair class to help you get started:
public class Pair {
private final int x;
private final int y;
public Pair(final int x, final int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Pair)) {
return false;
}
final Pair pair = (Pair) o;
if (x != pair.x) {
return false;
}
if (y != pair.y) {
return false;
}
return true;
}
#Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
You just write tiles.get(new Pair(0, 0)), just like you did for put.
You will need to override the methods .equals() and .hashCode() for your Pair() type. They are needed in order to use a type in a HashMap. Equals can just check that the 2 values are equal:
#Override public boolean equals(Object o) {
if(this == o) return true;
if(!(o instanceof Pair)) return false;
Pair p = (Pair)o;
return p.x == x && p.y == y;
}
For hashCode, you must generate a value that is unique:
private volatile int hashCode; // define this as a member of the class
#Override public int hashCode() {
int result = hashCode;
if(result == 0) {
result = 17 * x + 31 * y;
hashCode = result;
}
return result;
}
Then you can access the cell at (0, 0) by simply calling
tiles.get(new Pair(0, 0));
You need to override hashCode(). Something like:
public int hashCode() {
return 17 * this.key + 31 * this.value;
}
The following code does not give me right answer.
class Point {
int x; int y;
public Point(int a,int b){
this.x=a;this.y=b;
}
}
class A{
public static void main(String[] args){
ArrayList<Point> p=new ArrayList<Point>();
p.add(new Point(3,4));
p.add(new Point(1,2));
System.out.println(p.indexOf(1,2));
}
}
This gives -1;
In general if arraylist of point is given, how can we find index of a particular point in in array ?
indexOf requires the object as input. If it does not find the object you are passing in, it will return -1. You need to pass the object whose location in the arraylist you are looking for as the input into the indexOf function. You should also override hashcode and equals for your class in this case.
Override hashcode and equals in your class Point. Then once you create instances of this class Point (using the new keyword) and add them to the arrayList, you can use the indexOf call on the arrayList using any of the Point objects as a parameter to the indexOf call.
Class Point
public class Point {
int x;
int y;
public Point(int a, int b) {
this.x=a;this.y=b;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
Class Test (you called it "a"):
import java.util.ArrayList;
public class Test {
public static void main(String[] args){
ArrayList<Point> p=new ArrayList<Point>();
Point p1 = new Point(3,4);
Point p2 = new Point(1,2);
p.add(new Point(3,4));
p.add(new Point(1,2));
System.out.println(p.indexOf(p1));
}
}
You need to create a point to pass into the indexOf method.
p.indexOf(new Point(1,2));
But that change by itself will still return -1. See the api doc for indexOf:
public int indexOf(Object o)
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
It's using equals to decide whether it's found a match. You haven't overridden the equals method on your point class, so it's using the default implementation in java.lang.Object, which compares the references, and only returns true if the two references point to the same object.
Override equals and hashcode on your point class, like:
#Override public boolean equals(Object other) {
if (!(other instanceof point)) {
return false;
}
point otherPoint = (point)other;
return otherPoint.x == this.x && otherPoint.y == this.y;
}
#Override public int hashCode() {
return x + y; // same values should hash to the same number
}
and that way two different instances of the class can be compared by value.
ArrayList.indexOf() doesn't accept two integers as argument. You must input one object, which is supposed to be a Point object.
If you still want to call ArrayList.indexOf(int, int), then you must create a subclass of ArrayList, implementing indexOf(int,int).
The following code should find the wanted object for you. First, you'll need to override the equals method from the Object class in the Point class, in order to compare two points.
public class Point {
private int x;
private int y;
#Override
public boolean equals(Object anotherObject) {
if (!(anotherObject instanceof Point)) {
return false;
}
Point p = (Point) anotherObject;
return (this.x == p.x && this.y == p.y);
}
}
Second, you can call indexOf(Object):
ArrayList<Point> p = new ArrayList<Point>();
// Create the point to find in the list.
Point findMe = new Point(1,2);
// Search the array and save the found index.
int index = p.indexOf(findMe);
PS: You should follow the Java naming conventions; classes must start with an uppercase letter.
how can we find index of a particular point in in array ?
ArrayList<point> p=new ArrayList<point>();
point p1 = new point(3,4));
point p2 = new point(1,2));
p.add(p1);
p.add(p2);
System.out.println(p.indexOf(p1));
The argument to indexOf() is an Object. Pass it one of your point objects.
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?
I'm working on a polynomial calculator. My problem is with the equals method. Here is the relevant code:
public class Poly{
Term[] terms;
//Constructors-------------------------------------------
public Poly() {}
public Poly(ArrayList<Term> Terms) {
terms = Terms.toArray(new Term[Terms.size()]);
Arrays.sort(terms, new TermComparator());
}
//Methods-------------------------------------------------
public boolean equals(Poly x) {
boolean q=false;
if(this == x){
q=true;
}
return q;
}
//used in constructor to order terms
class TermComparator implements Comparator<Term> {
#Override
public int compare(Term t1, Term t2) {
return t2.getExp() - t1.getExp();
}
}
}
The equals method always returns false even when two Poly objects have the same value. Can anyone help please?
Your Poly class equals method should be like below
#Override
public boolean equals(Object obj) {
if (this == obj) //checking both are same instance
return true;
if (obj == null) // checking obj should not be null
return false;
if (getClass() != obj.getClass()) //checking both objects from same class
return false;
Poly other = (Poly) obj;
return Arrays.equals(terms, other.terms); //checking all the array values
}
if you are adding Poly objects to collection you need to implement hash code method too.
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(terms);
return result;
}
Please refer
Why do I need to override the equals and hashCode methods in Java?
How should equals and hashcode be implemented when using JPA and Hibernate
It seems you need the following 2 changes:
Do not compare references using code as follows:
if(this == x){
q=true;
}
You need to compare the content of the object - the contents of terms in your case.
When overriding the equals method, you'd better override the hashcode method as well.
My solution involved creating an equals method in the term class first. You would then use that equals method to write the equals method in the polynomial class. So here's the code for the equals method for terms:
public boolean equals(Term x){
boolean a= false;
int expThis = this.getExp();
int coefThis = this.getCoeff();
int expX = x.getExp();
int coefX = x.getCoeff();
if(expThis==expX && coefThis==coefX){
a=true;
}
return a;
}
My polynomial constructor already organizes all terms in decreasing order. If you have polynomials in order then all you have to do is first check that the two polynomials are the same size and then loop through all the terms of the two polynomials, using the equals method from the term class to compare terms. So here's the code for the equals method for polynomials:
public boolean equals(Object obj) {
boolean w=false;
Poly other = (Poly) obj;
int L1 = other.terms.length;
int L2 = this.terms.length;
if(L1==L2){
for(int q=0; q<L1; q++){
Term a=other.terms[q];
Term b=this.terms[q];
if(a.equals(b)==true){
w=true;
}
else{
w=false;
break;
}
}
}
return w;
}