Overriding hashCode() not working - java

I'm trying to make class Point work correctly with a HashSet. Here is my Point class:
class Point {
int x;
int y;
Point(int x, int y) {
x = x;
y = y;
}
#Override
public int hashCode() {
int hash = 1;
hash = hash * 17 + x;
hash = hash * 31 + y;
return hash;
}
#Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
Point p = (Point) o;
return x == p.x && y == p.y;
}
}
When I test it out and do
HashSet<Point> h = new HashSet<Point>();
h.add(new Point(0, 0));
Point g = new Point(0, 1);
System.out.println(h.equals(g));
System.out.println(h.contains(g));
The output is this
false
true
Why is my hashCode not working?

In
Point(int x, int y) {
x = x;
y = y;
}
You are assigning x, the local parameter variable, to itself. Same for y. These are no-ops.
Use
Point(int x, int y) {
this.x = x;
this.y = y;
}
so that you assign the parameter value to the field.
As others have noted, you shouldn't do
Point p = (Point) o;
without knowing if o is a Point or not. It will throw a ClassCastException if it is not assignable to a Point. Instead use
if (o instanceof Point)
return false;
or
if (o.getClass() != Point.class)
return false;
before casting. Note that the two methods above are not equivalent. You can use the first in most cases, but use the second if Point is meant to have sub classes.

Related

How to make two objects equal in contains method of Hashset [duplicate]

This question already has answers here:
What issues should be considered when overriding equals and hashCode in Java?
(11 answers)
Closed last year.
I have created a Pair Class which has 3 variables mentioned below and overrides the equals method as well assuming this is used in contains method of hashset. But it is not. Can someone explain what to implement in Pair class to make sure it equats the values of x and y only.
Class Pair extends Object {
int x;
int y;
int dis;
public Pair(int x, int y, int d) {
this.x = x;
this.y = y;
this.dis = d;
}
#override
public boolean equals(Pair p) {
return this.x == p.x && this.y == p.y
}
}
Whenever you overide equals, you should also override hashCode:
#Override
public int hashCode() {
return Objects.hash(x,y);
}
See the general contract of equals and hashCode:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html
It is generally necessary to override the hashCode method whenever equals method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
import java.util.HashSet;
class Point extends Object {
int x, y, dis;
Point(int x, int y) {
this.x = x;
this.y = y;
this.dis = (int) Math.sqrt(x * x + y * y);
}
#Override
public boolean equals(Object o) {
if (o instanceof Point) {
Point p = (Point) o;
return p.x == x && p.y == y;
}
return false;
}
#Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public class Equals {
public static void main(String[] args) {
HashSet<Point> set = new HashSet<Point>();
set.add(new Point(1, 2));
set.add(new Point(1, 2));
set.add(new Point(1, 3));
System.out.println(set.size());
}
}
See equals API doc.

How does Java execute the Collections.contains() method, Could anyone pls show some links to this? [duplicate]

This question already has answers here:
Why do I need to override the equals and hashCode methods in Java?
(31 answers)
Closed 2 years ago.
Met an issue with the contains() method, not sure why it behaves differently in the two scenarios, as the following code snippet shows:
import java.awt.*;
import java.util.LinkedHashSet;
import java.util.Set;
public class SetDemo01 {
public static void main(String[] args) {
Set<Point> set = new LinkedHashSet<>();
Point a = new Point(0, 1);
Point b = new Point(0, 1);
set.add(a);
System.out.println(set.contains(b));
Set<Coordinate> set02 = new LinkedHashSet<>();
Coordinate c = new Coordinate(0, 1);
Coordinate d = new Coordinate(0, 1);
set02.add(c);
System.out.println(set02.contains(d));
}
}
class Coordinate {
int x;
int y;
Coordinate (int x, int y) {
this.x = x;
this.y = y;
}
}
The console prints:
true
false
Now I knew I need to override the equals() & hashCode() methods, but could someone pls show the reference for this: when apply the contains() method, the equals() is run, and the 'hashCode' is compared.
If you declare your class like that, you would have your expected output:
class Coordinate {
int x;
int y;
Coordinate (int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Coordinate that = (Coordinate) o;
return x == that.x &&
y == that.y;
}
#Override
public int hashCode() {
return Objects.hash(x, y);
}
}
Without overriding the equals method the contains method will only look if the two objects are the same reference.
Please have also a look at: Why do I need to override the equals and hashCode methods in Java?

Java make custom object comparable?

I have the object below.
public class Coords {
public int x;
public int z;
public Coords(int x, int z) {
this.x = x;
this.z = z;
}
}
How can this implement Compareable?
Im not sure what the compareTo method should be doing.
#Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
You could compare x and then compare z (alternatively, z and then x). Also, I suggest you override toString. Something like,
public class Coords implements Comparable<Coords> {
public int x;
public int z;
public Coords(int x, int z) {
this.x = x;
this.z = z;
}
#Override
public int compareTo(Coords o) {
if (this.x == o.x) {
if (this.z == o.z) {
return 0;
}
return this.z < o.z ? -1 : 1;
}
return this.x < o.x ? -1 : 1;
}
#Override
public String toString() {
return String.format("{%d, %d}", x, z);
}
}
Here are the details of compareTo:
Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
I'd suggest something like this:
#Override
public int compareTo(Coords other) {
return this.x == other.x ? (this.z == other.z ? 0 : this.z - other.z) : this.x - other.x
You can make z more significant if you switch them.

How to make my HashMap work as expected?

Suppose one has a simple class:
public class Point implements Comparable<Point> {
public int compareTo(Point p) {
if ((p.x == this.x) && (p.y == this.y)) {
return 0;
} else if (((p.x == this.x) && (p.y > this.y)) || p.x > this.x) {
return 1;
} else {
return -1;
}
}
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
And a HashMap from Point to something, let's say Cell:
cellMap = new HashMap<Point, Cell>();
Then one fills in cellMap as follows:
for (int x = -width; x <= width; x++) {
for (int y = -height; y <= height; y++) {
final Point pt = new Point(x,y);
cellMap.put(pt, new Cell());
}
}
}
And then one does something like (trivial) this:
for (Point pt : cellMap.keySet()) {
System.out.println(cellMap.containsKey(pt));
Point p = new Point(pt.getX(), pt.getY());
System.out.println(cellMap.containsKey(p));
}
And gets true and false in, respectively, first and second cases. What is going on? Is this map comparing hashes instead of values? How to make the example return true in both cases?
Since you are using HashMap, not TreeMap, you need to override hashCode and equals, not compareTo, in your Point class:
#Override
public int hashCode() {
return 31*x + y;
}
#Override
public bool equals(Object other) {
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof Point)) return false;
Point p = (Point)other;
return x == p.x && y == p.y;
}

.get(key) wont give me my value in a Hashmap<Point, Integer>

I'm a bit new to programming and wanted to try making a more difficult box style 2d game for learning then my previous game. Alas I'm still new so please dumb down your answer if possible.
I've been toying around with hash maps for a few hours now and cant seem to figure out why feeding java my key wont give me its value back.
package main;
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
}
public Map<Point, Integer> Blocks = new HashMap<Point, Integer>();
int x = 0;
int y = 0;
while (active == true) {
Point Apple = new Point(x, y);
Blocks.put(Apple, 1);
if (x <= 800) {
x += 32;
} else {
x = 0;
y += 32;
}
if (y > 600) {
active = false;
}
}
MouseX = (Mouse.getX() / 32) * 32;
MouseY = (Mouse.getY() / 32) * 32;
Point rawr = new Point(MouseX, MouseY);
if (Blocks.containsKey(rawr)) {
y = Blocks.get(rawr);
}
I get y = 0 instead of y = 1 as a result. Thanks for any help given.
You fail to obey the most fundamental contract of java: the .equals()/.hashCode() contract.
You need to override them both in class Point. There are many examples here on SO and on the net in general.
Now, why this applies here is because you try and see if the blocks map contains a Point which you have instantiated. But keys in a HashMap, which you use, rely heavily on .equals() and .hashCode(). It .contains(x) if and only if there is one key of the map k such that k.equals(x).
For your class:
#Override
public int hashCode()
{
return 31 * x + y;
// If using Java 7, this can be:
// returns Objects.hash(x, y);
}
#Override
public boolean equals(final Object o)
{
// No object instance is equal to null
if (o == null)
return false;
// If the object is the same, this is true
if (this == o)
return true;
// If not the same object class, false
if (getClass() != o.getClass())
return false;
final Point other = (Point) o; // safe to cast since getClass() == o.getClass()
return x == other.x && y == other.y; // test instance member equality
}
The root problem is that your Point key has the wrong semantics for its equals method. You are using the equals method inherited from from Object, and that method says that two objects are "equal" if-and-only-if they are the same object.
So suppose you create (say) a point instance as new Point(1,1) and use it as the key to add an entry to the hash table. Then when you want to do a lookup of the point at (1,1), you create a second point instance (with new Point(1,1)) ... and call get(...). But this new point is a different point object (p1.equals(p2) is `false'!)... so the lookup fails.
The solution is to override equals in your Point class so that two Point objects are "equal" if they have the same x and y attributes. You then need to override hashcode so the equals() / hashcode() contract is met.
Here's an example:
//
// The fields are 'final' because we want make it clear that a Point
// is immutable. The class itself is 'final' to simplify the problem of
// testing for equality. (Equality between an instance of a class and
// an instance of a subclass can be problematic. If the subclass overrides
// the `equals` method you get in problems with the requirement that equality
// is symmetric; i.e. ensuring that 't.equals(st) == st.equals(t)'. Making
// Pint `final` removes that potential issue.)
//
public final class Point {
private final int x;
private final int y;
public Point(int x, int y) { this.x = x; this.y = y; }
public int getX() { return this.x; }
public int getY() { return this.y; }
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof Point)) {
return false;
}
Point point = (Point) other;
return this.x = point.x && this.y == point.y;
}
public int hashcode() {
return this.x + 31 * this.y;
}
}

Categories