I try to create a tuple class that allows a tuple-like structure in Java. The general type for two elements in tuple are X and Y respectively. I try to override a correct equals for this class.
Thing is, I know Object.equals falls into default that it still compares based on references like "==", so I am not so sure I can use that. I looked into Objects and there is an equals() in it. Does this one still compare on references, or it compares on contents?
Quickly imagined the return statement as something like:
return Objects.equals(compared.prev, this.prev) && Objects.equals(compared.next, this.next);
where prev and next are elements of tuple. Would this work?
The difference is the Objects.equals() considers two nulls to be "equal". The pseudo code is:
if both parameters are null or the same object, return true
if the first parameter is null return false
return the result of passing the second parameter to the equals() method of the first parameter
This means it is "null safe" (non null safe implementation of the first parameter’s equals() method notwithstanding).
this is literal code from java source: as you can see, #Agent_L is right
The answer to your question "Does this one [Objects.equals] still compare on references, or it compares on contents?" - Objects.equals does some comparisons on the references but it expects the first argument's class to implement equals() in which the comparison of contents is done as well as on reference.
Your second question about the implementation of equals in your tupple-like class having prev and next as its tupple attributes the answer is: your suggested implementation would work only if
prev and next are primitives or if their type implements equals properly.
So if prev for example is of type Foo, then you can use Objects.equals to test the two Foo's only if class Foo implements equals as expected.
Objects.equals just calls it's first arguments .equals method. In java, if you want to be able to test for equality in instances of a class you made, then you have to override the equals method. instance.equals() only uses == if that instances type doesn't override the equals method.
Related
I know that if a.equals(b), we must have a.hashCode() == b.hashCode() else we get strange results, but I'm wondering if the converse is also required.
More specifically, I have a hashCode() function that uses the field id to calculate the hashCode. However, my equals() function only uses the simple comparison "==" to check for equality. This may seem strange but unless more details are required, it's simply how I've implemented it.
Now the question is will this mess anything up? Specifically for HashSets, but more generally, for any (common) implementations of Set.
The way I understand it, a Set will first check the hashCode then the equals operator to see if a duplicate object exists. In this case, it should work right? If two objects are the same instance, they will produce the same hashCode as well as return true for equals() and thus the Set will only allow the instance to be be added once.
For two separate instances with the same id, the hashCode will be identical but then the equals() operator will return false and thus allow both objects to enter the Set, which is what I hope to accomplish.
Is this a beginner's mistake? Am I missing something? Will this have an unexpected results for any collection types other than Set?
edit:
I guess I should explain myself. I have a Hibernate object FooReference which implements both a hashCode and equals method using the id. This object is guaranteed to always have a unique id. However, before this object is persisted, I use a Foo object which has a default id of -1. So when putting it in a Set (to be saved) I know each Foo is unique (thus the basic == operator). So this Foo which extends FooReference overrides the equals method with a basic ==. For my purposes this should work... hopefully.
Objects are allowed to have the same hashcode without being equal to each other. In fact, it's perfectly valid (though inefficient and a bad idea) to implement hashCode as simply return 0, giving every instance the same hashcode.
All that's required is that if two objects are equal (as determined by the equals method), they have the same hashcode.
However, if your equals method just compares the two objects using == internally, no two (distinct) instances will ever be equal to each other, so there's no point defining your own hashCode and equals methods at all. The default implementations will produce the same behavior.
I've noticed that you can't compare 2 points like this:
if (pointOne == pointTwo) { }
I always have to do it like this:
if (pointOne.x == pointTwo.x && pointOne.y == pointTwo.y) { }
I really wonder why you can not use the first example, does anyone have an answer?
You must use the equals method of class Point. Check this.
If you use == what you are actually doing is checking if the memory address of the two Point objects is the same.
In Java, all classes are derived from Object, and you can override the equals method, providing a convenient way of checking if in fact, two objects of the same Object derived class, are the same.
== operator checks both reference pointing to the same object or not.
You should use equals method of Point object -
pointOne.equals(pointTwo);
Determines whether or not two points are equal. Two instances of
Point2D are equal if the values of their x and y member fields,
representing their position in the coordinate space, are the same.
Documentation
Because the Point is reference, and if you need to use equals, you need to override the method equal. Java doest not support override operators like "==".
I assume pointOne and pointTwo are objects of some class? You cannot overload operators in java, that is why you have to compare fields.
In such cases it is a good practive to override the equals method for your class and use it this way:
PointOne.equals(PointTwo)
Well this will be an object comparison. You would be comparing memory locations if you compare using ==.
You could override and call Equals.
You can use your first example because running pointOne.x == pointTwo.x compares the primitive types (int) which the == operator is capable of.
When you run pointOne == pointTwo you're comparing the Point object references, which they're not.
As others have said, you can use pointOne.equals(pointTwo)
I am trying to check wether mylist contains a given object or not, where mylist is an ArrayList of type myCustomClass.
If you add an instance of MyCustomClass to the list, and then check if it contains another instance of MyCustomClass, it will always return false, unless you override the equals method in your custom class. The equals method checks if another object is functionally equal to this object.
Make sure to override the hashCode method each time you override the equals method. hashCode should return the same value for two equal objects. Also, equals should be written so that it's symmetric: a.equals(b) if and only if b.equals(a).
Check equals and hashCode in the javadoc of java.lang.Object.
You most likely haven't implemented equals() and hashcode() on myCustomClass. You need to implement them properly and according to contract, see here for details of how.
Is this code:
elem1!=elem2
equivalent to this one?
!elem1.equals(elem2)
It compiles both ways, but I'm still unsure about it...
== (and by extension !=) check for object identity, that is, if both of the objects refer to the very same instance. equals checks for a higher level concept of identity, usually whether the "values" of the objects are equal. What this means is up to whoever implemented equals on that particular object. Therefore they are not the same thing.
A common example where these two are not the same thing are strings, where two different instances might have the same content (the same string of characters), in which case a == comparison is false but equals returns true.
The default implementation of equals (on Object) uses == inside, so the results will be same for objects that do not override equals (excluding nulls, of course)
In general, no they're not the same. The first version checks whether elem1 and elem2 are references to the same object (assuming that they're not primitive types). The second version calls a type-specific method to check whether two (possibly distinct) ojects are "equal", in some sense (often, this is just a check that all their member fields are identical).
I don't think this has anything to do with generics, as such.
I have the following situation: I need to sort trees based by height, so I made the Tree's comparable using the height attribute. However, I was also told to overwrite the equals and hashCode methods to avoid unpredictable behaviour.
Still, sometimes I may want to compare the references of the roots or something along those lines using ==. Is that still possible or does the == comparison call the equals method?
equals() is meant to compare an object with rules set by the programmer. In your example you compare your trees by height, so you'll write equals() so it compares heights.
==, as you said, compares references. These aren't touched neither by equals() nor by hashCode(). So you won't change its behaviour.
Yes, == will not call hashCode or equals. You can still test for reference equality like this.
== does not call equals. So it's still find for identity checks.
As many implementations of equals start with this == other check you would get a literal StackOverflow if it were calling equals behind the scenes.
I think that a bigger question here is whether it is appropriate to implement comparable on these objects. It may be more appropriate to use a Comparator for the operations that work on height, and not embed ordinal computation in the class itself.
My general philosophy on this is to only implement Comparable if there is a truly natural ordering for the object. In the case of a tree node, is height the only way that anyone could ever want to sort? Maybe this is a private class, and the answer is 'yes'. But even then, creating a Comparator isn't that much extra work, and it leaves things flexible in case you decide you want to make that tree node a protected or public class some day.
== tests referential equality. It will not call equals.
Overriding the equals() method will have NO effect on the == operator.
== is used to test if 2 references point to the same object.
equals() method "meaningfully" compares 2 objects.
It is important to realize the implication of the work "meaningful" here. Equality is easier to understand when you are comparing, for instance, 2 Strings or 2 integers. This is why, the equals() method - inherited from the Object class - is already overridden by the String and Wrapper classes (Integer, Float, etc). However, what if you are comparing 2 objects of type Song. Here, equality can be established on the basis of
1) Artist name
2) Song name
3) or some other criterion
Therefore, you have to override the equals() method to "explicitly" determine "when" 2 Song objects are considered equal.
The "unpredictable behavior" you mentioned in your question relates to objects like the one above (Song) behave when dealing with Collections like Map. You SHOULD NOT use these objects in a map until you override both the equals() and hashcode() method. The reason being how hashmap search and indexing works. Refer the JavaDoc for the specifc rules. What you should remember is:
If 2 objects are meaningfully equal, their hashcode should return the same value. However, it is not necessary for 2 objects to be equal, if they return the same hashcode. Again, Java doesn't enforce any rules regarding this. It is your responsibility to implement the equals() and hashcode() methods correctly.