Java HashSet contains function not working - java

I am writing a simple program as follow: Given two numbers M and N, p is from [M,N] and q is from [1,p-1], find all irreducible fractions of p/q.
My idea is brute force all possible value of p, q. And using HashSet to avoid duplicated fraction. However, somehow the contains function not working as expected.
My code
import java.util.HashSet;
import java.util.Set;
public class Fraction {
private int p;
private int q;
Fraction(int p, int q) {
this.p = p;
this.q = q;
}
public static int getGCD(int a, int b) {
if (b == 0)
return a;
else
return getGCD(b, a % b);
}
public static Fraction reduce(Fraction f) {
int c = getGCD(f.p, f.q);
return new Fraction(f.p / c, f.q / c);
}
public static HashSet<Fraction> getAll(int m, int n) {
HashSet<Fraction> res = new HashSet<Fraction>();
for (int p = m; p <= n; p++)
for (int q = 1; q < p; q++) {
Fraction f = new Fraction(p,q);
Fraction fr = reduce(f);
if (!res.contains(fr))
res.add(fr);
}
return res;
}
public static void print(Fraction f) {
System.out.println(f.p + "/" + f.q);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
HashSet<Fraction> res = getAll(2, 4);
for (Fraction f : res)
print(f);
}
}
Here is the output of program
4/3
3/1
4/1
2/1
3/2
2/1
you can see the fraction 2/1 is duplicated. Anyone can help me figure out why and how to fix it.
Many thanks.

Override the Object#equals and Object#hashCode methods in the Fraction class. These methods are used by HashSet to determine if two objects are the same. When you don't override them, the equals method tests equality of the objects' references rather that equality of their field values.
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + p;
result = prime * result + q;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Fraction other = (Fraction) obj;
if (p != other.p)
return false;
if (q != other.q)
return false;
return true;
}

You need to implement Fraction#equals() and Fraction#hashcode(), because that is used for determining weather the set contains certain value or not. Without it, object references are compared, which will not give you the desired result.

Your Fraction class does not override hashCode and equals. A HashMap contains tries to find a key with the same hashCode (and equals) as the one you provided. As you create a new instance of Fraction, it will never be the same as the one already in the HashMap. Here is how you would do hashCode and equals:
#Override
public int hashCode() {
return super.hashCode() + p * 24 + q * 24;
}
#Override
public boolean equals(Object other) {
if (!(other instanceof Fraction)) return false;
return ((Fraction) other).p == this.p && ((Fraction) other).q == this.q;
}

Related

hashCode(): return of an integer after string

I don't understand in this code the hashcode() methode: how can you return an integer if there is a string... Basically you add a string next to a number but that doesn't maje it a string
also i don't understand the function equals, what is a object o and what is a o insteadof
public Imatriculation(int numeros, String word) {
this.numeros = numeros;
this.word = word;
}
public int hashCode() {
return this.word.hashCode() + this.numeros;
}
public boolean equals(Object o) {
return o instanceof Imatriculation
&& this.word.equals(((Imatriculation) o).word)
&& this.numeros == ((Imatriculation) o).numeros;
}
As was already pointed out hashcode returns an int not a string.
"o" is simply any object in java, it could be anything, so instanceof is used to check if object "o" is an Imatriculation before going on and checking the details of the object.
String#hashCode() is overriden from Object#hashCode() thus it also returns int. From the String source:
public int hashCode() { // <- it returns int!!!
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
The main purpose of hashCode() is "numerically represent" instance of a class in order to determine, which bucket of hash table it should occupy.

Deep equal issue about boolean method with a Object argument

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;
}

assertEquals not comparing HashSet java [duplicate]

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?

Example of 2 objects in java having same hash value but equals method returns false on them

We all know that if equals method returns true, then two objects are equal.
Can anybody give an example where 2 objects have the same hash value but they are actually different?
I'm assuming you're familiar with the contract(s) associated with overriding equals() and hashCode(), and the implications of a collision-prone hashCode implementation. Given that, the following trivial example uses an object that holds two Integers and implements a very simple hashCode, and demonstrates how easy it is to have two objects that aren't equal but have the same hashCode. Providing a more sophisticated hashCode algorithm can alleviate this.
The output of running main is:
hashCodes: ih1: 6, ih2: 6
equals: false
Example code:
package example.stackoverflow;
public class IntHolder
{
private Integer primaryData;
private Integer secondaryData;
public IntHolder(Integer primaryData, Integer secondaryData)
{
this.primaryData = primaryData;
this.secondaryData = secondaryData;
}
#Override
public int hashCode()
{
return ((primaryData == null) ? 0 : primaryData.hashCode()) +
((secondaryData == null) ? 0 : secondaryData.hashCode());
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IntHolder other = (IntHolder) obj;
if (primaryData == null)
{
if (other.primaryData != null)
return false;
}
else if (!primaryData.equals(other.primaryData))
return false;
if (secondaryData == null)
{
if (other.secondaryData != null)
return false;
}
else if (!secondaryData.equals(other.secondaryData))
return false;
return true;
}
public static void main(String[] args)
{
IntHolder ih1 = new IntHolder(1, 5);
IntHolder ih2 = new IntHolder(3, 3);
System.out.println("hashCodes: ih1: " + ih1.hashCode() + ", ih2: " + ih2.hashCode());
System.out.println("equals: " + ih1.equals(ih2));
}
}
For reference, Eclipse's auto-generated hashCode() for the IntHolder class is:
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result
+ ((primaryData == null) ? 0 : primaryData.hashCode());
result = prime * result
+ ((secondaryData == null) ? 0 : secondaryData.hashCode());
return result;
}
String str1="abcdef";
String str2="abcdfG";
They both have the same hashcode and equals method returns false.
public class Employee {
protected long employeeId;
public boolean equals(Object o){
if(o == null) return false;
if(!(o instanceof) Employee) return false;
Employee other = (Employee) o;
return this.employeeId == other.employeeId;
}
public int hashCode(){
return (int) this.employeeId;
}
}
In this example, we have overridden the equals method - two employees are equal when they will have same employee id.
If two Employee objects are equal, they will also have the same hash code.
Your Ans -
In this example, we also implemented the hash code - hashcode is the employeeId that is rounded down to an int. That means that many employee id's could result in the same hash code, but these Employee objects would still not be equal, since they don't have the same employee id.

polynomial arithmetic java equals method

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;
}

Categories