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;
}
Related
I fill up an Array List with some numbers and want to find a specific number that is in the Array List and get its position (the index) in my Array List.
Any example would be great!
for example
ProClon.indexOf(spro.getId(id));
First override equals() method with the specified field. then You can use indexOf.(object)
class A {
int i;
// other fields
public A(int i) {
this.i = i;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
A a = (A) o;
return i == a.i;
}
#Override
public int hashCode() {
return i;
}
}
List<A> list = new ArrayList<>();
list.indexOf(new A(3));
check the api of arrayList. indexOf(Object o); does exactly what you need.
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#indexOf(java.lang.Object)
Just use method indexOf in array
arrayName.indexOf(object)
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;
}
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;
}
It looks like the hashCode() and equals() for int[] are poorly implemented, or not implemented at all!
(Tested with Android, but I expect it to be true for any Java environment).
In order to get HashSet.contains() working properly, I had to create a wrapper for int[] (plse, don't criticize my coding style, look at the essence):
public class IntArray {
private int[] value;
public IntArray(int[] value) {
this.value = value;
}
#Override
public int hashCode() {
int sum = 0;
// Integer overflows are cheerfully welcome.
for (int elem: value) sum += elem;
return sum;
}
#Override
public boolean equals(Object o) {
if (o == null) return (value==null);
if (value != null) {
if (o instanceof int[])
return compare((int[])o);
if (o instanceof IntArray)
return compare(((IntArray)o).value);
}
return false;
}
protected boolean compare(int[] other) {
int len = value.length;
if (other.length != len) return false;
for (int i=0; i<len ; i++)
if (value[i] != other[i]) return false;
return true;
}
}
Works OK, but I prefer to avoid a custom wrapper or a third-party library. Is there an option?
Since the standard Java Hashtable does not allow an override of the hash code used for keys, you are out of luck and will need to use a wrapper like you did.
keep in mind that your hashCode implementation is very bad, you can use this (Taken from java.util.Arrays in the standard JDK) to get a better hash distrubtion:
public static int hashCode(int a[]) {
if (a == null)
return 0;
int result = 1;
for (int element : a)
result = 31 * result + element;
return result;
}
An alternative is to use a different Hashtable, which can deal with primitives.
one such option is Banana, which is a primitive collections library I created.
After Omry Yadan's message the hashCode function becomes as simple as that!
#Override
public int hashCode() {
return Arrays.hashCode(value);
}
For a RISC CPU, like ARM, It may be more efficient:
#Override
public int hashCode() {
int code = 0;
if (value != null) {
code++;
for (int elem: value)
code = (code<<5) - code + elem;
}
return code;
}
May be there is also a standard function for comparing arrays, in which case equals() can be simplified too?
I have a List (actually a LinkedList) and I add Items to it which implement the equals-method.
The problem is that I add items that are equal, but not identical (like two initialized objects). Now, when I want to get the index of the item I added second, I get, of course, the element of the first item, because indexOf searches for equality and not identity.
I tried to create my own subclass of LinkedList and overwrite the indexOf-method, but this is not possible, because I don't have access to neither the subclass Node nor the Node-Element first.
Here is an example:
public class ExampleObject {
int number;
public ExampleObject(){
number = 0;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
ExampleObject other = (ExampleObject) obj;
if (number != other.number) return false;
return true;
}
public static void main(String[] args) {
LinkedList<ExampleObject> list = new LinkedList<ExampleObject>();
ExampleObject one = new ExampleObject();
ExampleObject two = new ExampleObject();
list.add(one);
list.add(two);
System.out.println(list.indexOf(one)); // '0' as expected
System.out.println(list.indexOf(two)); // '0', but I want to get '1'
}
}
My intention: I need a list of objects, where I want to store initialized objects and edit them later.
Do the iteration yourself, indexOf is just a helper method:
static int indexOfById(List<?> list, Object searchedObject) {
int i = 0;
for (Object o : list) {
if (o == searchedObject) return i;
i++;
}
return -1;
}
There are several solutions to this problem.
1) The correct solution: If you need identity comparison, then you should not override the equals method. You told us that you must override it, as you need it in another place. That indicates a design problem in your software, and you really should solve this.
2) Have a look at the class sun.awt.util.IdentityLinkedList. This is nearly a "normal" LinkedList with the identity behavior for the indexOf method. If you do not want to rely on a class in a sun sub-package, you can copy the code into a class that resides in your packages.
3) You could follow a procedural solution with iterating the list yourself:
public static <E> int indexOf(List<E> list, E searchItem) {
int index = 0;
for (E item : list) {
if (item == searchItem)
return index;
index += 1;
}
return -1;
}
4) Write a wrapper for your objects.
public class IdentityWrapper {
public Object item;
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
IdentityWrapper other = (IdentityWrapper) obj;
return item == other.item;
}
}
Then use this wrapper in your list: LinkedList<IdentityWrapper>. Note, that I provided a public item field in the wrapper. Normally, I would do it with a constructor and a private field only.