This is my implementation of the equals class for a Coor class which is just contains 2 ints x and y. would this be the proper way of implementing this method?
public boolean equals(Object obj) {
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
Coor temp = (Coor) obj;
if (temp.x == this.x && temp.y == this.y) {
return true;
} else {
return false;
}
}
You could add one more check for reflexive equality (equal to self):
public boolean equals(Object obj) {
// Reflexive equality: did I get passed myself?
if(this == obj){
return true;
}
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
Coor temp = (Coor) obj;
return temp.x == this.x && temp.y == this.y;
}
Yes, it would.
Also be sure to override your hashCode() method--never override one without doing the other as well, it will confuse the hell out of your collections.
Your case could use a hash where it simply shifts one of the ints 32 bits and adds it to the other creating a completely unique long (a perfect hash function in this case--no collisions)
Seems ok.
For brevity sake, you can do:
return temp.x == this.x && temp.y == this.y
Instead of
if (temp.x == this.x && temp.y == this.y) {
return true;
} else {
return false;
}
Also, please keep in mind the Object Contract (seriously!).
See the accepted answer here:
What issues should be considered when overriding equals and hashCode in Java?
This can save you a huge about of headache in the future.
Check this out:
http://www.javapractices.com/topic/TopicAction.do?Id=17
If that article is too much detail, then the short of it is:
Your implementation is correct, but you should keep some other things in mind:
You will also have to implement hashCode.
equals will no longer commpare the object's identity. Doesn't sound like that's a problem for you.
You could add the #Override annotation to your equals method.
Here’s a more straightforward way:
public boolean equals(Object other) {
return other instanceof Coor
&& ((Coor) other).x == x
&& ((Coor) other).y == y
}
I believe this would work, at a quick glance. I say this because:
It handles a null/improper types well.
Performing x.equals(y) would yield the same result as y.equals(x).
Performing x.equals(x) would return true.
Performing x.equals(y) == true and y.equals(z) == true implies that x.equals(z) == true
This question has certainly been asked many times before though. See here: Overriding equals and hashCode in Java. A book called Effective Java discusses this topic in great detail too, and the particular chapter is linked off of there.
There's only one source to read for how to override equals and hashCode: chapter 3 of Joshua Bloch's "Effective Java".
If you have a good IDE, like IntelliJ, it'll generate equals and hashCode the right way for you.
Related
The criteria is that equals() method where the objects are considered equal if the value of the double variable is within +/- 10 of the other object's value of the double variable.
I'm not sure how to correctly implement hashCode() so that the hashCode would be equal if it satisfies the conditions of the equals() method.
I would really appreciate your input! Thanks!
public class Test
{
private double value;
private boolean isEqualValues (final double valueOne, final double valueTwo)
{
if(valueOne == valueTwo)
{
return true;
}
else if((valueOne - valueTwo <= 10) &&
(valueOne - valueTwo >= -10))
{
return true;
}
else
{
return false;
}
#Override
public boolean equals(final Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
Test test = (Test) o;
if(isEqualValues(test.value, value))
{
return true;
}
else
{
return false;
}
}
//How to implement hashCode()
#Override
public int hashCode()
{
//unsure how to correctly implement hashCode() so that the hashCode would be equal if it
//satisfies the conditions of the equals() method above
}
}
There's no way to consistently implement this, since equals() demands transitivity:
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
new Test(1), new Test(9) and new Test(14) would fail that test (assuming a trivial one-argument constructor that assigns its argument to value).
One way to work around that is to not check for the absolute distance, but "categorize" your objects using some formula, for example take the floor of value / 10 and compare that.
This way some "close" values like new Test(9) and new Test(11) would compare as not-equal, but other than that you'd get a similar result to what you described.
private long getEquivalenceGroup() {
return Math.floorDiv((long) value, 10);
}
#Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Test test = (Test) o;
return test.getEquivalenceGroup() == this.getEquivalenceGroup();
}
#Override
public int hashCode()
{
return Long.hashCode(getEquivalenceGroup());
}
As long as getEquivalenceGroup() is implemented in a stable manner this will produce "groups" of slightly different objects that still compare as equal and has a valid hashCode() implementation.
Note: if you want a comparison as described in the question but you don't necessarily need it to be returned by equals() then adding a boolean isClose(Test other) is perfectly fine. The only problem is you are trying to implement the equals method specifically with that semantic.
You can't and you shouldn't.
You should implement a comparator and do such operations using that.
I'm programming a Maze and I have some problems.
I have:
HashSet<State> closedList = HashSet<State>(); //it hold State objects
My State class look like this:
public class State implements Comparable<State>{
private double f;
private double g;
private String state;
private State prev;
.
.
.
closedList.add(state);
closedList().contains(state); // this equals true
but when I do this:
State temp = State(0,0,"");
temp.setStateName(state.getStateName());
closedList().contains(temp); // this equals false
I have implemented equals and hashCode in State:
#Override
public int hashCode(){
return state.hashCode();
}
#Override
public boolean equals(Object object){
if(this.state == object){
return true;
}
if(object == null || object.getClass() != this.getClass()){
return false;
}
return false;
}
closedList().contains(state); // this equals true
This is a red herring, it only returns true because HashSet checks with == before it makes a call to equals.
What you should try is something like this:
State temp = new State(0, 0, "");
System.out.println(temp.equals(temp));
And you will find this returns false. Why is that? Well let's follow the logic through.
First, you have this check:
if(this.state == object){
return true;
}
If you really intended this to be the way it is, it means you were expecting equals to be called with the String state as the argument, like this:
temp.equals(temp.getStateName())
(And it's the case the above call would return true.) This is incorrect, one would not expect equals to return true for unrelated classes (and in terms of the equals contract, it's the case this is not symmetric). I assume this is unintended and just like a mistake. You should think more carefully about what your code is doing when you are writing it.
Also you should be comparing Strings with equals, not ==.
Then there is this construct:
if(object == null || object.getClass() != this.getClass()){
return false;
}
return false;
This is pointless because first what it implies logically is this, returning false either way:
if(object == null || object.getClass() != this.getClass()){
return false;
} else {
return false;
}
And, second, combined with the earlier check it is not particularly logical:
if(this.state == object)
return true;
if(object.getClass() != this.getClass())
return false;
This is returning true if object is == to a String but returning false if object's class is not State. These are mutually exclusive.
So the equals implementation you wrote doesn't work. The correct equals to match your hashCode is like this:
#Override
public boolean equals(Object object){
if(object == null || object.getClass() != this.getClass()){
return false;
}
State other = (State)object;
return this.state.equals(other.state);
}
First check that the object is not null and that its class is State (you had that part right), then check that the state member is equal to the other object's state member.
In a usage case, I have a HashMap which contains 1 entry and the key is A. I need to call get() with key B many many times. A equals() to B but A and B are not the same object. The Key contains a long array so its equals() is expensive. I am trying to improve the performance for this map checking operation. I know there are proper ways to address the performance issue. However, I am considering a hack which is the most expedient.
The following is from HashMap.java:
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}
if i change the if block in the for loop to:
if (e.hash == hash) {
if (e.key == key) {
return e.value;
} else if (e.key.equals(key)) {
e.key = (K) key;
return e.value;
}
}
I think it will help the performance a lot. The first time I call get() with key B, B's equals() will be called. For the rest of times, B will be == to the key in the map thus saves the equals() call.
However, it is not possible to just extend HashMap and override get() since HashMap.field is package protected and Entry.key is final.
Questions:
Will this scheme work?
Copying HashMap.java and its related code just to change one method is not very appealing. What is the best way to implement this hack?
Thanks!
This is a horrible idea. You are mutating an entry's key under the covers.
The solution is to create your own internal "identity hash value", something you can calculate and guarantee is unique for each value. Then use this as a proxy for the expensive comparison in your equals() method.
For example (pseudo-Java):
class ExpensiveEquals
{
private class InxpensiveEqualsIdentity
{
...
public InexpensiveEqualsIdentity(ExpensiveEquals obj) { ... }
public boolean equals() { an inexpensive comparison }
}
private InxpensiveEqualsIdentity identity;
public ExpensiveEquals(...)
{
... fill in the object
this.identity = new InexpensiveEqualsIdentity(this);
}
public int hashCode() { return this.identity.hashCode(); }
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || !o instanceof this.getClass()) return false;
return (this.identity.equals(((ExpensiveEquals)o).identity));
}
}
Yes, this should work, if equals is implemented properly (symmetric).
Try to hack equals method in the class of your map's keys:
equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof MyClass)) return false;
MyClass other = (MyClass) obj;
if (this.longArray == other.longArray) return true;
if (Arrays.equals(this.longArray, other.longArray)) {
this.longArray = other.longArray;
return true;
}
return false;
}
Since your class is immutable, this trick should be safe. Your should make longArray field non-final, but it won't hurt performance, I promise.
If B is the key you are really interested in, you can just perform the swap from the outside.
V val = map.remove(b);
map.put(b, val);
From then on, reference equality is sufficient for B but you aren't futzing with the internal mechanism.
My simple lazy idea built on top of #JimGarrison's answer:
private long hash0, hash1;
void initHash() {
// Compute a hash using md5 and store it in hash0 and hash1
// The collision probability for two objects is 2**-128, i.e., very small,
// and grows with the square of the number of objects.
// Use SHA-1 if you're scared.
}
void assureHash() {
if (hash0 == 0 && hash1 == 0) initHash();
}
public int hashCode() {
// If both hashes are zero, assume it wasn't computed yet.
assureHash();
return (int) hash0;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ExpensiveEquals)) return false;
ExpensiveEquals that = (ExpensiveEquals) o;
this.assureHash();
that.assureHash();
return this.hash0 == that.hash0 && this.hash1 == that.hash1;
}
This ensures that all equals invocations but the first will be pretty cheap. The changes that two randomly chosen pairs of longs are equals are negligible even when assuming thousands of objects and taking the birthday paradox into account. With a cryptographic hash function the numbers are as good as random.
If md5 and two longs aren't good enough, use SHA-1 and one additional int (that's what git does).
This equals() method will produce the same output if lines 3-5 are omitted (I numbered these lines). What is the point of these lines?
/** Return true if that Beetle has the same parts as this one. */
public boolean equals(Object that) {
3. if (this == that) {
4. return true;
5. }
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
Beetle thatBeetle = (Beetle) that;
return body == thatBeetle.body
&& eyes == thatBeetle.eyes
&& feelers == thatBeetle.feelers
&& head == thatBeetle.head
&& legs == thatBeetle.legs
&& tail == thatBeetle.tail;
}
Checking == reference equality is fast, and if true the object is being compared to itself -- so is by definition equal.
This is often used a first step when comparing objects, as it's much faster than comparing all the details. But it's more commonly used from the caller/client function, rather than inside the equals() implementation.
For example, in a linear search:
public int indexOfBeetle (Beetle beetle, List<Beetle> list) {
for (int i = 0; i < list.size(); i++) {
Beetle cand = list.get( i);
if (cand == beetle || cand.equals( beetle))
return i; // Found.
}
// Not Found.
return -1;
}
The operator == checks if the objects are the same instance in memory whereas when you override equals you usually want to perform a logical test.
Let's take an example:
public class Person {
private String name;
// Here there are constructor and getters and setters
}
Now let's run these lines:
Person a = new Person();
Person b = a;
Person c = new Person();
If you compare these instances with == this is what you'll get:
a == a ==> true
a == b ==> true
a == c ==> false
Now, let's set the name:
a.setName("Joe"); // This also sets b because they're the same object
c.setName("Joe");
If our equals looks like this:
public boolean equals (Object other) {
if(other == this) return true;
if(other instanceof Person == false) return false;
if(this.getName().equals(((Person) other).getName())) return true;
}
So we'll now get that a.equals(c) is true even though a==c is false.
So, why do we have the first line? - Some objects' equality is more expensive to compute and by checking this condition at the beginning you might spare some unnecessary computations
Doing that are you checking if the two objects are pointing to the same memory address. Using .equals without it you will achieve the same result because if they are pointing to the same memory address, it's obviously they are equals. But doing that it's much more faster, that's why most developers put this lines on .equals
List<Pair<String, String> > lp = new ArrayList<Pair<String, String> >();
lp.add(new Pair("1", "2"));
How should I check if the list lp contains 1 and 2 i.e the Pair ("1", "2").
Your Pair class needs to implement equals() and hashCode() and you're all set. List.contains() is implemented in terms of the type's equals() method. See the API for List.contains(). (Edited a bit to address comments from #maaartinus, whose answer you should read b/c the observations are solid, and it's a bit ridiculous for me to fold them in here. As maaartinus points out, a best-practice here would be to avoid error-prone manual definitions for equals and hashcode, and instead build on Guava's helper functions for nullable equals and hashCode for n objects).
final class Pair<T> {
final T left;
final T right;
public Pair(T left, T right)
{
if (left == null || right == null) {
throw new IllegalArgumentException("left and right must be non-null!");
}
this.left = left;
this.right = right;
}
public boolean equals(Object o)
{
// see #maaartinus answer
if (! (o instanceof Pair)) { return false; }
Pair p = (Pair)o;
return left.equals(p.left) && right.equals(p.right);
}
public int hashCode()
{
return 7 * left.hashCode() + 13 * right.hashCode();
}
}
With suitable equals(), you can now do:
lp.add(new Pair("1", "2"));
assert lp.contains(new Pair("1","2"));
Responding to the comments below, perhaps it would be good to include a good reference for "Why do I need to implement hashCode()?"
JavaPractices.com — Implementing equals() — "if you override equals, you must override hashCode"
Object.equals() contract as defined in the API documentation
StackOverflow answer
The implementation in the answer by andersoj
return left != null && right != null && left.equals(p.left) && right.equals(p.right);
is wrong: The null tests clearly suggest that null is a legal value for left and right. So there are at least two problems there:
new Pair(null, null).hashCode() throws NPE
new Pair(null, null) does NOT equal to itself!
Have a look at Guava class Objects for a correct implementation. Use it or write a static helper methods like
public static boolean equal(Object a, Object b) {
return a==b || a!=null && a.equals(b);
}
public static int hashCode(Object a) {
return a==null ? 0 : a.hashCode();
}
and always use them.
Never ever write equals containing a null test.
It's to easy to blow it, and nobody noticed it. Using the Helper, it's trivial to get it right:
public boolean equals(Object o) {
if (!(o instanceof Pair)) return false;
Pair p = (Pair) o;
return Helper.equals(left, p.left) && Helper.equals(right, p.right);
}
public int hashCode() {
return 7 * Helper.hashCode(left) + 13 * Helper.hashCode(right);
}
Of course, forbidding nulls in the constructor is an option, too.