Is it okay to have a hashcode as a simple increment? - java

Is this code below okay for a hashCodeto be a simple increment starting with a negative number?
private volatile static AtomicInteger creations = new AtomicInteger(Integer.MIN_VALUE);
private final int creation;
{
creation = creations.getAndIncrement();
}
#Override
public int hashCode() {
return creation;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
if (creation == ((Stuff) obj).creation)
return true;
else
return false;
}
How come hashCodes are usually made with prime numbers instead of using just a simple increment? (The reason why I want it to be this way is because each object I create with this class will be unique and I want to be able to remove it from a HashMap later even though the state of the object will change, because it is my understanding if a Hash changes then you cannot remove it from a HashMap after it was added) To prevent this from being a simple yes or no answer, maybe explain to me the pros and cons of implementing a Hash this way.

In general it's not okay. Two objects for which object1.equals(object2) returns true must have the same hashCode.
However, in your specific case, where the only criteria for object equality is the creation property, which is the same property used in the hashCode, your hashCode is fine.
However, your hashCode and equals don't offer much benefit over the default implementations of Object, since a.equals(b) will be true if and only if a==b.

Yes it's ok (if two instances are equals, they have the same hashcode) although your equals/hashcode implementation is not doing much vs. the default implementation of Object so there is no point doing that - unless you want objects to be equal every 2^32 instance creation.
Based on your additions, I would agree with Patricia Shanahan's suggestion to use identityHashCode:
#Override
public int hashCode() {
return System.identityHashCode(this);
}
#Override
public boolean equals(Object obj) {
return this == obj;
}
That is essentially what Object does by default. In terms of collisions, I doubt that you will have more collision with this implementation than yours.

Related

Boolean value differs with calling println for method call and calling print ln for variable containing boolean return value of method call [duplicate]

I ran into an interesting (and very frustrating) issue with the equals() method today which caused what I thought to be a well tested class to crash and cause a bug that took me a very long time to track down.
Just for completeness, I wasn't using an IDE or debugger - just good old fashioned text editor and System.out's. Time was very limited and it was a school project.
Anyhow -
I was developing a basic shopping cart which could contain an ArrayList of Book objects. In order to implement the addBook(), removeBook(), and hasBook() methods of the Cart, I wanted to check if the Book already existed in the Cart. So off I go -
public boolean equals(Book b) {
... // More code here - null checks
if (b.getID() == this.getID()) return true;
else return false;
}
All works fine in testing. I create 6 objects and fill them with data. Do many adds, removes, has() operations on the Cart and everything works fine. I read that you can either have equals(TYPE var) or equals(Object o) { (CAST) var } but assumed that since it was working, it didn't matter too much.
Then I ran into a problem - I needed to create a Book object with only the ID in it from within the Book class. No other data would be entered into it. Basically the following:
public boolean hasBook(int i) {
Book b = new Book(i);
return hasBook(b);
}
public boolean hasBook(Book b) {
// .. more code here
return this.books.contains(b);
}
All of a sudden, the equals(Book b) method no longer works. This took a VERY long time to track down without a good debugger and assuming the Cart class was properly tested and correct. After swaapping the equals() method to the following:
public boolean equals(Object o) {
Book b = (Book) o;
... // The rest goes here
}
Everything began to work again. Is there a reason the method decided not to take the Book parameter even though it clearly was a Book object? The only difference seemed to be it was instantiated from within the same class, and only filled with one data member. I'm very very confused. Please, shed some light?
In Java, the equals() method that is inherited from Object is:
public boolean equals(Object other);
In other words, the parameter must be of type Object. This is called overriding; your method public boolean equals(Book other) does what is called overloading to the equals() method.
The ArrayList uses overridden equals() methods to compare contents (e.g. for its contains() and equals() methods), not overloaded ones. In most of your code, calling the one that didn't properly override Object's equals was fine, but not compatible with ArrayList.
So, not overriding the method correctly can cause problems.
I override equals the following everytime:
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof MyClass)) return false;
MyClass otherMyClass = (MyClass)other;
...test other properties here...
}
The use of the #Override annotation can help a ton with silly mistakes.
Use it whenever you think you are overriding a super class' or interface's method. That way, if you do it the wrong way, you will get a compile error.
If you use eclipse just go to the top menu
Source --> Generate equals() and
hashCode()
Slightly off-topic to your question, but it's probably worth mentioning anyway:
Commons Lang has got some excellent methods you can use in overriding equals and hashcode. Check out EqualsBuilder.reflectionEquals(...) and HashCodeBuilder.reflectionHashCode(...). Saved me plenty of headache in the past - although of course if you just want to do "equals" on ID it may not fit your circumstances.
I also agree that you should use the #Override annotation whenever you're overriding equals (or any other method).
Another fast solution that saves boilerplate code is Lombok EqualsAndHashCode annotation. It is easy, elegant and customizable. And does not depends on the IDE. For example;
import lombok.EqualsAndHashCode;
#EqualsAndHashCode(of={"errorNumber","messageCode"}) // Will only use this fields to generate equals.
public class ErrorMessage{
private long errorNumber;
private int numberOfParameters;
private Level loggingLevel;
private String messageCode;
See the options avaliable to customize which fields to use in the equals. Lombok is avalaible in maven. Just add it with provided scope:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.14.8</version>
<scope>provided</scope>
</dependency>
in Android Studio is
alt + insert ---> equals and hashCode
Example:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Proveedor proveedor = (Proveedor) o;
return getId() == proveedor.getId();
}
#Override
public int hashCode() {
return getId();
}
Consider:
Object obj = new Book();
obj.equals("hi");
// Oh noes! What happens now? Can't call it with a String that isn't a Book...
the instanceOf statement is often used in implementation of equals.
This is a popular pitfall !
The problem is that using instanceOf violates the rule of symmetry:
(object1.equals(object2) == true) if and only if (object2.equals(object1))
if the first equals is true, and object2 is an instance of a subclass of
the class where obj1 belongs to, then the second equals will return false!
if the regarded class where ob1 belongs to is declared as final, then this
problem can not arise, but in general, you should test as follows:
this.getClass() != otherObject.getClass(); if not, return false, otherwise test
the fields to compare for equality!
recordId is property of the object
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Nai_record other = (Nai_record) obj;
if (recordId == null) {
if (other.recordId != null)
return false;
} else if (!recordId.equals(other.recordId))
return false;
return true;
}

Deep comparison for HashSet in Java [duplicate]

I ran into an interesting (and very frustrating) issue with the equals() method today which caused what I thought to be a well tested class to crash and cause a bug that took me a very long time to track down.
Just for completeness, I wasn't using an IDE or debugger - just good old fashioned text editor and System.out's. Time was very limited and it was a school project.
Anyhow -
I was developing a basic shopping cart which could contain an ArrayList of Book objects. In order to implement the addBook(), removeBook(), and hasBook() methods of the Cart, I wanted to check if the Book already existed in the Cart. So off I go -
public boolean equals(Book b) {
... // More code here - null checks
if (b.getID() == this.getID()) return true;
else return false;
}
All works fine in testing. I create 6 objects and fill them with data. Do many adds, removes, has() operations on the Cart and everything works fine. I read that you can either have equals(TYPE var) or equals(Object o) { (CAST) var } but assumed that since it was working, it didn't matter too much.
Then I ran into a problem - I needed to create a Book object with only the ID in it from within the Book class. No other data would be entered into it. Basically the following:
public boolean hasBook(int i) {
Book b = new Book(i);
return hasBook(b);
}
public boolean hasBook(Book b) {
// .. more code here
return this.books.contains(b);
}
All of a sudden, the equals(Book b) method no longer works. This took a VERY long time to track down without a good debugger and assuming the Cart class was properly tested and correct. After swaapping the equals() method to the following:
public boolean equals(Object o) {
Book b = (Book) o;
... // The rest goes here
}
Everything began to work again. Is there a reason the method decided not to take the Book parameter even though it clearly was a Book object? The only difference seemed to be it was instantiated from within the same class, and only filled with one data member. I'm very very confused. Please, shed some light?
In Java, the equals() method that is inherited from Object is:
public boolean equals(Object other);
In other words, the parameter must be of type Object. This is called overriding; your method public boolean equals(Book other) does what is called overloading to the equals() method.
The ArrayList uses overridden equals() methods to compare contents (e.g. for its contains() and equals() methods), not overloaded ones. In most of your code, calling the one that didn't properly override Object's equals was fine, but not compatible with ArrayList.
So, not overriding the method correctly can cause problems.
I override equals the following everytime:
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof MyClass)) return false;
MyClass otherMyClass = (MyClass)other;
...test other properties here...
}
The use of the #Override annotation can help a ton with silly mistakes.
Use it whenever you think you are overriding a super class' or interface's method. That way, if you do it the wrong way, you will get a compile error.
If you use eclipse just go to the top menu
Source --> Generate equals() and
hashCode()
Slightly off-topic to your question, but it's probably worth mentioning anyway:
Commons Lang has got some excellent methods you can use in overriding equals and hashcode. Check out EqualsBuilder.reflectionEquals(...) and HashCodeBuilder.reflectionHashCode(...). Saved me plenty of headache in the past - although of course if you just want to do "equals" on ID it may not fit your circumstances.
I also agree that you should use the #Override annotation whenever you're overriding equals (or any other method).
Another fast solution that saves boilerplate code is Lombok EqualsAndHashCode annotation. It is easy, elegant and customizable. And does not depends on the IDE. For example;
import lombok.EqualsAndHashCode;
#EqualsAndHashCode(of={"errorNumber","messageCode"}) // Will only use this fields to generate equals.
public class ErrorMessage{
private long errorNumber;
private int numberOfParameters;
private Level loggingLevel;
private String messageCode;
See the options avaliable to customize which fields to use in the equals. Lombok is avalaible in maven. Just add it with provided scope:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.14.8</version>
<scope>provided</scope>
</dependency>
in Android Studio is
alt + insert ---> equals and hashCode
Example:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Proveedor proveedor = (Proveedor) o;
return getId() == proveedor.getId();
}
#Override
public int hashCode() {
return getId();
}
Consider:
Object obj = new Book();
obj.equals("hi");
// Oh noes! What happens now? Can't call it with a String that isn't a Book...
the instanceOf statement is often used in implementation of equals.
This is a popular pitfall !
The problem is that using instanceOf violates the rule of symmetry:
(object1.equals(object2) == true) if and only if (object2.equals(object1))
if the first equals is true, and object2 is an instance of a subclass of
the class where obj1 belongs to, then the second equals will return false!
if the regarded class where ob1 belongs to is declared as final, then this
problem can not arise, but in general, you should test as follows:
this.getClass() != otherObject.getClass(); if not, return false, otherwise test
the fields to compare for equality!
recordId is property of the object
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Nai_record other = (Nai_record) obj;
if (recordId == null) {
if (other.recordId != null)
return false;
} else if (!recordId.equals(other.recordId))
return false;
return true;
}

How to compare private data fields of objects to ensure they are the same (Java)?

Just to start off here, this is homework/a lab and I'm looking for advice. I am developing a very small program that is essentially a counter with a min/max value constraint and a method that pushes the value up and another that rolls the value back to zero 0. So, the private data fields I have for my Counter class are:
private int minimum;
private int maximum;
private int currentValue;
The trouble I am having here is with a method that compares my Counter Class to another theoretical object based off the same class. In this case, we're looking to see that the data fields between the two objects are the same. I have researched several ways of doing this including using reflections and the famous EqualsBuilder, but am having trouble implementing each.
Here's the code that they've given me.
public boolean equals(Object otherObject)
{
boolean result = true;
if (otherObject instanceof Counter)
{
}
return result;
}
Assuming your equals method is in the Counter class, it has access to all the private members of that class, even if they are members of a different instance of that class.
public boolean equals(Object otherObject)
{
if (otherObject instanceof Counter)
{
Counter ocounter = (Counter) otherObject;
if (this.minimum != ocounter.minimum)
return false;
...
} else {
return false;
}
return true;
}
Implementing the equals-method can be a real pain, especially if you have a lot of properties in your class.
The JavaDoc for the equals-method states
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
And, if you check the JavaDoc for the hashCode-method.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
Therefore, it is typically recommended that you implement both methods (equals and hashCode). The following shows one way of doing this that is based on the java.util.Objects-class that came with Java 7. The method Objects.equals(Object, Object) handles null checks which makes the code simpler and easier to read. Furthermore, the hash-method is a convenient way of creating values that can be used with hashCode.
So, to answer your question. In order to access the attributes of your other object, simply perform a type cast. After that you can access the other object's private properties. But, remember to always do this after you have checked the type using instanceof.
#Override
public boolean equals(Object other) {
if (other instanceof Counter) { // Always check the type to be safe
// Cast to a Counter-object
final Counter c = (Counter) other;
// Now, you can access the private properties of the other object
return Objects.equals(minimum, c.minimum) &&
Objects.equals(maximum, c.maximum) &&
Objects.equals(currentValue, c.currentValue);
}
return false; // If it is not the same type, always return false
}
#Override
public int hashCode() {
return Objects.hash(currentValue, maximum, minimum);
}
As equals is a method of Counter, you can access all the private fields of Counter, so you can do something like this:
if (otherObject instanceof Counter)
{
if (this.minimum != ((Counter) otherObject).minimum) {
result = false;
}
// [...]
}
Assuming your class is called Counter and you created getters for all the private fields (that you should do):
#Override
public boolean equals(Object other) {
boolean result = false;
if (other instanceof Counter) {
Counter c= (Counter) other;
result = (this.getMinimum() == that.getMinimum() &&
this.getMaximum() == that.getMaximum() &&
this.getCurrentValue() == that.getCurrentValue());
}
return result;
}

Hash function for a generic object

How do you come up with a hash function for a generic object? There is the constraint that two objects need to have the same hash value if they are "equal" as defined by the user. How does Java accomplish this?
I just found the answer to my own question. The way Java does it is that it defines a hashCode for every object and by default the hashCode for two objects are the same iff the two objects are the same in memory. So when the client of the hashtable overrides the equals() method for an object, he should also override the method that computes hashcode such that if a.equals(b) is true, then a.hashCode() must also equal b.hashCode(). This way, it is assured that equal objects have the same hashcode.
First, basically you define the hash function of a class by overriding the hashCode() method. The Javadoc states:
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
So the more important question is: What makes two of your objects equal? Or vice versa: What properties make your objects unique? If you have an answer to that, create an equals() method that compares all of the properties and returns true if they're all the same and false otherwise.
The hashCode() method is a bit more involved, I would suggest that you do not create it yourself but let your IDE do it. In Eclipse, you can select Source and then Generate hashCode() and equals() from the menu. This also guarantees that the requirements from above hold.
Here is a small (and simplified) example where the two methods have been generated using Eclipse. Notice that I chose not to include the city property since the zipCode already uniquely identifies the city within a country.
public class Address {
private String streetAndNumber;
private String zipCode;
private String city;
private String country;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((country == null) ? 0 : country.hashCode());
result = prime * result
+ ((streetAndNumber == null) ? 0 : streetAndNumber.hashCode());
result = prime * result + ((zipCode == null) ? 0 : zipCode.hashCode());
return result;
}
#Override
public boolean equals(final Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(!(obj instanceof Address))
return false;
final Address other = (Address) obj;
if(country == null) {
if(other.country != null)
return false;
}
else if(!country.equals(other.country))
return false;
if(streetAndNumber == null) {
if(other.streetAndNumber != null)
return false;
}
else if(!streetAndNumber.equals(other.streetAndNumber))
return false;
if(zipCode == null) {
if(other.zipCode != null)
return false;
}
else if(!zipCode.equals(other.zipCode))
return false;
return true;
}
}
Java doesn't do that. If the hashCode() and equals() are not explicitly implemented, JVM will generate different hashCodes for meaningfully equal instances. You can check Effective Java by Joshua Bloch. It's really helpful.
Several options:
read Effective Java, by Joshua Bloch. It contains a good algorithm for hash codes
let your IDE generate the hashCode method
Java SE 7 and greater: use Objects.hash
The class java.lang.Object cheats. It defines equality (as is determined by equals) as being object identity (as can be determined by ==). So, unless you override equals in your subclass, two instances of your class are "equal", if they happen to be the same object.
The associated hash code for this is implemented by the system function System.identityHashCode (which is no longer really based on object addresses -- was it ever? -- but can be thought of as being implemented this way).
If you override equals, then this implementation of hashCode no longer makes sense.
Consider the following example:
class Identifier {
private final int lower;
private final int upper;
public boolean equals(Object any) {
if (any == this) return true;
else if (!(any instanceof Identifier)) return false;
else {
final Identifier id = (Identifier)any;
return lower == id.lower && upper == id.upper;
}
}
}
Two instances of this class are considered equal, if their "lower" and "upper" members have the same values. Since equality is now determined by object members, we need to define hashCode in a compatible way.
public int hashCode() {
return lower * 31 + upper; // possible implementation, maybe not too sophisticated though
}
As you can see, we use the same fields in hashCode which we also use when we determine equality. It is generally a good idea to base the hash code on all members, which are also considered when comparing for equality.
Consider this example instead:
class EmailAddress {
private final String mailbox;
private final String displayName;
public boolean equals(Object any) {
if (any == this) return true;
else if (!(any instanceof EmailAddress)) return false;
else {
final EmailAddress id = (EmailAddress)any;
return mailbox.equals(id.mailbox);
}
}
}
Since here, equality is only determined by the mailbox member, the hash code should also only be based on that member:
public int hashCode() {
return mailbox.hashCode();
}
Hashing of an object is established by overriding hashCode() method, which the developer can override.
Java uses prime numbers in the default hashcode calculation.
If the equals() and hashCode() method aren't implemented, the JVM will generate hashcode implicitly for the object (for Serializable classes, a serialVersionUID is generated).

How to properly implement equals in Java

I need to implement the equals method in some class A. Class A has an orderer collection of Enum type, and the behaviour I want to achive is that equals returns true for two instances of Class A that have exactly the same Enum values in the collection (in exactly the same positions of the collection).
As I'm new to java, I'm having problems with this, and I dont know how to properly implement equals or the hashcode methods, so any help would be good :)
If you're using eclipse (netbeans has similar features, as do most java IDEs), you can simply got to the "Source" menu, and choose "Generate hashcode() and equals()". Then you select the fields you want to be considered (in your case the list of enum values.
That being said, assuming you already have the enum, here's the code that eclipse generated for me. Not that hashcode usually involves a prime number, as well as multiplication and addition. This tends to give you somewhat decent distribution of values.
public class Foo {
private List<FooEnum> enumValues;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((enumValues == null) ? 0 : enumValues.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Foo other = (Foo) obj;
if (enumValues == null) {
if (other.enumValues != null)
return false;
}
else if (!enumValues.equals(other.enumValues))
return false;
return true;
}
}
The overridden equals method will look like this
public boolean equals(Object o) {
if ((o instanceof yourtype) &&
(((yourtype)o).getPropertyToTest() == this.propertyToTest)) {
return true;
}
else {
return false;
}
}
The overridden hashCode method will look like this
public int hashCode() { return anIntRepresentingTheHashCode}
Pulling from the javadocs, your equals method must meet the following criteria:
reflexive - x.equals(x) is true
symmetric - if x.equals(y) then y.equals(x)
transitive - if x.equals(y) and y.equals(z) then x.equals(z)
consistent - if x.equals(y) is true, then it's always true unless the object is modified
null - x.equals(null) is false
Also, if two objects are equal based on the equals method, they must have identical hash codes.
The reverse is not true. If two objects are not equal, they may or may not have identical hash codes
Use EnumSet It retains natural order as per java docs also and it is optimized for Enums only.
The iterator returned by the iteratormethod traverses the elements in their natural order (the order in which the enum constants are declared). The returned iterator is weakly consistent: it will never throw ConcurrentModificationException and it may or may not show the effects of any modifications to the set that occur while the iteration is in progress.
You can use EnumSet as below
import java.util.EnumSet;
public enum Direction {
LEFT,
RIGHT,
ABOVE,
BELOW;
private static EnumSet<Direction> someDirection = EnumSet.of(Direction.LEFT,Direction.RIGHT) ;
}
Now because you are using EnumSet equals and Hashcode method will be provided default from AbstractSet which is parent class of EnumSet
So You don't have to care about them.

Categories

Resources