Lluis Martinez
Lluis Martinez

Reputation: 1973

Compact equals and hashcode

I have a bean with 4 attributes:

user
institutionId
groupId
postingDate

I use Eclipse to generate equals and hashcode but the resulting code is not pretty. Is there a compact way to do the same? Assuming I want equals & hashcode to use all the attributes or a subset of them.

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((groupId == null) ? 0 : groupId.hashCode());
    result = prime * result + ((institutionId == null) ? 0 : institutionId.hashCode());
    result = prime * result + ((postingDate == null) ? 0 : postingDate.hashCode());
    result = prime * result + ((user == null) ? 0 : user.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;
    ManGroupKey other = (ManGroupKey) obj;
    if (groupId == null) {
        if (other.groupId != null)
            return false;
    } else if (!groupId.equals(other.groupId))
        return false;
    if (institutionId == null) {
        if (other.institutionId != null)
            return false;
    } else if (!institutionId.equals(other.institutionId))
        return false;
    if (postingDate == null) {
        if (other.postingDate != null)
            return false;
    } else if (!postingDate.equals(other.postingDate))
        return false;
    if (user == null) {
        if (other.user != null)
            return false;
    } else if (!user.equals(other.user))
        return false;
    return true;
}

Upvotes: 5

Views: 1147

Answers (6)

Puce
Puce

Reputation: 38132

hashCode: Either:

@Override 
public int hashCode() {
    return Objects.hash(user, institutionId, groupId, postingDate);
}

Or:

@Override 
public int hashCode() {
    int result = 17;
    result = 31 * result + Objects.hashCode(user);
    result = 31 * result + Objects.hashCode(institutionId);
    result = 31 * result + Objects.hashCode(groupId);
    result = 31 * result + Objects.hashCode(postingDate);
    return result;
}

Equals:

public boolean equals(Object obj){
    if (obj == this){
        return true;
    }
    if (! (obj instanceof ManGroupKey)){
        return false;
    }
    ManGroupKey other = (ManGroupKey) obj;
    return Objects.equals(user, other.user)
           && Objects.equals(institutionId, other.institutionId)
           && Objects.equals(groupId, other.groupId)
           && Objects.equals(postingDate, other.postingDate);
}

Upvotes: 2

Leonard Brünings
Leonard Brünings

Reputation: 13222

In Java 7


public int hashCode() {
    return Objects.hash(groupId, institutionId, postingDate, user);
}


public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;

    // cast to correct class
    Target o = (Target)obj;

    return Objects.equals(groupId, o.groupId) &&
           Objects.equals(institutionId, o.institutionId) &&
           Objects.equals(postingDate, o.postingDate) &&
           Objects.equals(user, o.user);
}

Upvotes: 6

Boris Brodski
Boris Brodski

Reputation: 8695

I think the library, that can suite you is apache common. It provides EqualsBuilder and HashCodeBuilder classes, that do exactly what you are looking for.

Consider this question for details: Apache Commons equals/hashCode builder

Here are some code snippets:

public class Bean{

    private String name;
    private int length;
    private List<Bean> children;


    @Override
    public int hashCode(){
        return new HashCodeBuilder()
            .append(name)
            .append(length)
            .append(children)
            .toHashCode();
    }

    @Override
    public boolean equals(final Object obj){
        if(obj instanceof Bean){
            final Bean other = (Bean) obj;
            return new EqualsBuilder()
                .append(name, other.name)
                .append(length, other.length)
                .append(children, other.children)
                .isEquals();
        } else{
            return false;
        }
    }
}

Upvotes: 1

WarriorOfKnight
WarriorOfKnight

Reputation: 86

Instead of using the eclipse generated code, you can use Apache-common-langs(http://commons.apache.org/proper/commons-lang/) class HashCodeBuilder and EqualsBuilder to do this:

public int hashCode() {
   return HashCodeBuilder.reflectionHashCode(this);
}


public boolean equals(Object obj) {
   return EqualsBuilder.reflectionEquals(this);
 }

Upvotes: 4

Jeroen Vannevel
Jeroen Vannevel

Reputation: 44439

You can at least remove one level of nesting by removing the other.x != null check.

Comparing a value in this way: x.equals(y) will always return false when y is null.

Aside from that: the .equals() method is a good example where a bit of reflection can be handy, possible extracted out into a generic utility method. All you have to do is run through the different fields and see if they're equal in the two objects, that can be done in a few lines.

Obviously that is only feasible when you actually want to compare each field (or you'll have to add some additions to it which let you choose the fields).

Upvotes: 1

Tim B
Tim B

Reputation: 41178

You could compact the code down, but the odds are far higher that you would introduce bugs than that you would do anything useful. All the parts of the equals and hash code method are there for a reason.

If it's bothering you most IDEs have a folding editor, just click the little yellow box (usually) and all the contents of the method get hidden away.

Upvotes: 5

Related Questions