【问题标题】:Overriding hashcode method for class with lists of objects as fields用对象列表作为字段覆盖类的哈希码方法
【发布时间】:2013-12-11 18:27:03
【问题描述】:

从这一点开始,我有一个类(A),它有 4 个字段、3 个对象数组列表和 1 个字符串数组列表。我已经相应地覆盖了equals和hashcode方法,我创建了A类的多个对象并添加到一个hashmap中以获得一些逻辑。但是对于具有相同值的随机对象,我得到不同的哈希码值,因此当我尝试 hashmap.get(object) 随机失败时,感谢任何帮助,下面是类。

import java.util.ArrayList;
import java.util.List;

import com.makinglifeeasy4u.util.AddressBean;
import com.makinglifeeasy4u.util.EmailBean;
import com.makinglifeeasy4u.util.PhoneBean;

public class ContactsMainBean {

    String contact_id;
    String name;
    private List<PhoneBean> phonelist = new ArrayList<PhoneBean>();
    private List<EmailBean> emaillist = new ArrayList<EmailBean>();
    private List<AddressBean> addressbean = new ArrayList<AddressBean>();
    private List<String> notesList = new ArrayList<String>();

    public String getContact_id() {
        return contact_id;
    }

    public void setContact_id(String contact_id) {
        this.contact_id = contact_id;
    }

    public List<String> getNotesList() {
        return notesList;
    }

    public void setNotesList(List<String> notesList) {

        if (this.notesList != null && this.notesList.size() > 0) {
            this.notesList.addAll(notesList);
        } else {
            this.notesList = notesList;
        }
        // this.notesList = notesList;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<PhoneBean> getPhonelist() {
        return phonelist;
    }

    public void setPhonelist(List<PhoneBean> phonelist) {
        if (this.phonelist != null && this.phonelist.size() > 0) {
            this.phonelist.addAll(phonelist);
        } else {
            this.phonelist = phonelist;
        }

    }

    public List<EmailBean> getEmaillist() {

        return emaillist;
    }

    public void setEmaillist(List<EmailBean> emaillist) {
        if (this.emaillist != null && this.emaillist.size() > 0) {
            this.emaillist.addAll(emaillist);
        } else {
            this.emaillist = emaillist;
        }
        // this.emaillist = emaillist;
    }

    public List<AddressBean> getAddressbean() {
        return addressbean;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((addressbean == null) ? 0 : addressbean.hashCode());
        result = prime * result
                + ((emaillist == null) ? 0 : emaillist.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result
                + ((notesList == null) ? 0 : notesList.hashCode());
        result = prime * result
                + ((phonelist == null) ? 0 : phonelist.hashCode());
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof ContactsMainBean)) {
            return false;
        }
        ContactsMainBean other = (ContactsMainBean) obj;
        if (addressbean == null) {
            if (other.addressbean != null) {
                return false;
            }
        } else if (!addressbean.equals(other.addressbean)) {
            return false;
        }
        if (emaillist == null) {
            if (other.emaillist != null) {
                return false;
            }
        } else if (!emaillist.equals(other.emaillist)) {
            return false;
        }
        if (name == null) {
            if (other.name != null) {
                return false;
            }
        } else if (!name.equals(other.name)) {
            return false;
        }
        if (notesList == null) {
            if (other.notesList != null) {
                return false;
            }
        } else if (!notesList.equals(other.notesList)) {
            return false;
        }
        if (phonelist == null) {
            if (other.phonelist != null) {
                return false;
            }
        } else if (!phonelist.equals(other.phonelist)) {
            return false;
        }
        return true;
    }

    public void setAddressbean(List<AddressBean> addressbean) {

        if (this.addressbean != null && this.addressbean.size() > 0) {
            this.addressbean.addAll(addressbean);
        } else {
            this.addressbean = addressbean;
        }
        // this.addressbean = addressbean;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        // return getName()+":"+getPhonelist();
        return getName() + ":" + getPhonelist() + ":" + getEmaillist() + ":"
                + getAddressbean() + ":" + getNotesList() + ":"
                + name.hashCode() + ":" + phonelist.hashCode() + ":"
                + emaillist.hashCode() + ":" + notesList.hashCode();
    }

}

我在 phonebean、emailbean、addressbean 中重写了 hashcode 和 equals 方法。

添加beanobject代码:

  public class PhoneBean {

    String type;
    String number;

    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((number == null) ? 0 : number.hashCode());
        //result = prime * result + ((type == null) ? 0 : type.hashCode());
        return result;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        PhoneBean other = (PhoneBean) obj;
        if (number == null) {
            if (other.number != null)
                return false;
        } else if (!number.equals(other.number))
            return false;
//      if (type == null) {
//          if (other.type != null)
//              return false;
//      } else if (!type.equals(other.type))
//          return false;
        return true;
    }

@Override
public String toString() {
    // TODO Auto-generated method stub
    return getNumber();
}

}

电子邮件 bean:

public class EmailBean {

    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getEmailType() {
        return emailType;
    }
    public void setEmailType(String emailType) {
        this.emailType = emailType;
    }
    String email;
    String emailType;
    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((email == null) ? 0 : email.hashCode());
        result = prime * result
                + ((emailType == null) ? 0 : emailType.hashCode());
        return result;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        EmailBean other = (EmailBean) obj;
        if (email == null) {
            if (other.email != null)
                return false;
        } else if (!email.equals(other.email))
            return false;
        if (emailType == null) {
            if (other.emailType != null)
                return false;
        } else if (!emailType.equals(other.emailType))
            return false;
        return true;
    }

}

地址豆:

public class AddressBean {

     String poBox;
     String street;
     String city;
     String state;
     String postalCode;
     String country;
     String addresstype;
    public String getPoBox() {
        return poBox;
    }
    public void setPoBox(String poBox) {
        this.poBox = poBox;
    }
    public String getStreet() {
        return street;
    }
    public void setStreet(String street) {
        this.street = street;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public String getPostalCode() {
        return postalCode;
    }
    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }
    public String getCountry() {
        return country;
    }
    public void setCountry(String country) {
        this.country = country;
    }
    public String getAddresstype() {
        return addresstype;
    }
    public void setAddresstype(String addresstype) {
        this.addresstype = addresstype;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((addresstype == null) ? 0 : addresstype.hashCode());
        result = prime * result + ((city == null) ? 0 : city.hashCode());
        result = prime * result + ((country == null) ? 0 : country.hashCode());
        result = prime * result + ((poBox == null) ? 0 : poBox.hashCode());
        result = prime * result
                + ((postalCode == null) ? 0 : postalCode.hashCode());
        result = prime * result + ((state == null) ? 0 : state.hashCode());
        result = prime * result + ((street == null) ? 0 : street.hashCode());
        return result;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        AddressBean other = (AddressBean) obj;
        if (addresstype == null) {
            if (other.addresstype != null)
                return false;
        } else if (!addresstype.equals(other.addresstype))
            return false;
        if (city == null) {
            if (other.city != null)
                return false;
        } else if (!city.equals(other.city))
            return false;
        if (country == null) {
            if (other.country != null)
                return false;
        } else if (!country.equals(other.country))
            return false;
        if (poBox == null) {
            if (other.poBox != null)
                return false;
        } else if (!poBox.equals(other.poBox))
            return false;
        if (postalCode == null) {
            if (other.postalCode != null)
                return false;
        } else if (!postalCode.equals(other.postalCode))
            return false;
        if (state == null) {
            if (other.state != null)
                return false;
        } else if (!state.equals(other.state))
            return false;
        if (street == null) {
            if (other.street != null)
                return false;
        } else if (!street.equals(other.street))
            return false;
        return true;
    }


}

奇怪的是,如果我在类的 tostring() 中 sysout 下面的代码。我得到以下结果

return getName() + ":" + getPhonelist() + ":" + getEmaillist() + ":"
                + getAddressbean() + ":" + getNotesList() + ":"
                + name.hashCode() + ":" + phonelist.hashCode() + ":"
                + emaillist.hashCode() + ":" + notesList.hashCode();

结果:

12-12 00:25:20.133: I/System.out(2317): *拨号 Airtel:[321]:[]:[]:[]:346070743:50672:1:1
12-12 00:25:20.133: I/System.out(2317): *拨号 Airtel:[321]:[]:[]:[]:346070743:50672:1:1
12-12 00:25:20.143: I/System.out(2317): *拨号 Airtel:[321]:[]:[]:[]:346070743:50672:1:1
12-12 00:25:20.143: I/System.out(2317): *拨号 电信:[321]:[]:[]:[]:346070743:50672:1:31

【问题讨论】:

  • 我建议您创建一个简短但完整的程序来演示该问题。
  • 你所有的 bean 类型都覆盖 equals + hashcode 吗?例如,如果PhoneBean 没有,则将使用来自Object 的默认身份哈希码。
  • 我认为您在phonebeanemailbeanaddressbean 中的hashCode 实现可能有问题。你能展示这些吗?
  • 添加了 bean 类代码,Jon 我不知道在哪里做,有什么指示吗?出于某种原因,我觉得笔记列表是罪魁祸首,因为当我 sysout 列表对象的哈希码时,只有笔记列表哈希码不同,其他一切都一样
  • 我敢打赌,第二个列表实际上是一个包含一个元素的列表,即 "" 或 null,而第一个确实是一个空列表。

标签: java hashmap equals hashcode


【解决方案1】:

考虑使用(来自 org.apache.commons.lang.builder)EqualsBuilder 和 HashCodeBuilder 类,而不是构建您自己的哈希和等号,这将做正确的事情。

http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/EqualsBuilder.html

http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/HashCodeBuilder.html

例如你可以使用:

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

【讨论】:

    【解决方案2】:

    我认为您过度使用哈希码实现。您需要做的就是返回一个值,表明该对象可能等于另一个具有相同哈希码值的对象。

    为每个类选择一个其值不会改变的属性(通常是某种类型的 id),并为该类的 hashCode() 方法返回该特定值的哈希码。

    然后对于 equals() 方法,您只需比较该属性的值。

    【讨论】:

    • 同样不同的对象可能返回相同的哈希码也没问题。 Hashmap 甚至适用于所有返回相同哈希码的键(性能下降)。
    猜你喜欢
    • 2015-06-14
    • 2014-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多