Java HashMap找不到键,但它应该

Java HashMap找不到键,但它应该,java,map,Java,Map,我的应用程序中出现了一个奇怪的问题,我将快速解释全局架构,然后深入解释我的问题 我使用一个服务来填充一个来自我的数据库(JPA驱动)的HashMap,该数据库通过EJB远程方法调用(使用ApacheWicket)返回到我的视图。在这一部分中,我向返回的映射添加一个新的DomainObject,以存储来自最终用户的任何新值 当用户点击浏览器中的“添加”按钮时,问题就出现了。我试图在地图中检索新创建的项目,但失败了。通过使用调试器,我将面临以下问题 假设HashMap-map和DomainObjec

我的应用程序中出现了一个奇怪的问题,我将快速解释全局架构,然后深入解释我的问题

我使用一个服务来填充一个来自我的数据库(JPA驱动)的
HashMap
,该数据库通过EJB远程方法调用(使用ApacheWicket)返回到我的视图。在这一部分中,我向返回的映射添加一个新的
DomainObject
,以存储来自最终用户的任何新值

当用户点击浏览器中的“添加”按钮时,问题就出现了。我试图在地图中检索新创建的项目,但失败了。通过使用调试器,我将面临以下问题

假设
HashMap-map
DomainObject-do
是两个有趣的变量,我在调试器中得到了以下结果

map.keySet()
给我一个对应于
do
(即使@which simili引用是相同的)的对象,两个对象上的
hashcode()
返回相似的值,并且
在两个返回之间等于()

map.containsKey(do)返回
false

map.get(do)
;返回
null
,这很奇怪,因为我的密钥似乎在
映射中

假设我新创建的项是
keySet()
枚举的第一个键,我将执行以下操作:
map.get(新的ArrayList(map.keySet()).get(0))
,它返回null

如果可以的话,通过将断点附加到我的
DomainObject.equals()
DomainObject.hashcode()
方法,我发现
map.get()
只调用
hashcode()
而不是
equals()

我找到的唯一解决方法是在现有映射的基础上重新创建一个新映射
新HashMap(map)
,在这个新映射中,我完全可以通过其键查找对象

我希望这里有人能给我指点一下会发生什么,谢谢

使用的环境:

  • OS X 10.7.1下的Sun Java 1.6.0_26 x64
  • Debian 6.0.2(2.6.32)下的OpenJDK 1.6.0_18 x64
  • ApacheWicket 1.4.17
  • 甲骨文玻璃鱼3.1.1
  • JBoss Hibernate 3.6.5
DomainObject
code:

public class AssetComponentDetailTemplate extends BaseEntite<Long> {
public enum DataType {
    TXT,
    DATE,
    INT,
    JOIN,
    LIST,
    COULEURS,
    REFERENCE
}

public enum Tab {
    IDENTITE,
    LOCALISATION,
    CYCLE_DE_VIE,
    FINANCE,
    RESEAU,
    DETAIL
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private DataType dataType;
private Integer classNameId;
private Long orderId;
private Long nextAssetComponentDetailTemplateId;
private String unit;
@Enumerated(EnumType.STRING)
private Tab tab;

@Column(nullable = false)
private Long uniqueOrganizationId;

@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "idAssetComponentDetailTemplate", insertable = false, updatable = false)
private List<AssetComponentDetailJoin> assetComponentDetailJoins;

private Boolean mandatory = false;

public AssetComponentDetailTemplate() {
}

public Long getId() {
    return id;
}

public void setId(final Long id) {
    this.id = id;
}

public String getName() {
    return name;
}

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

public DataType getDataType() {
    return dataType;
}

public void setDataType(final DataType dataType) {
    this.dataType = dataType;
}

public Integer getClassNameId() {
    return classNameId;
}

public void setClassNameId(final Integer classNameId) {
    this.classNameId = classNameId;
}

public Long getUniqueOrganizationId() {
    return uniqueOrganizationId;
}

public void setUniqueOrganizationId(final Long uniqueOrganizationId) {
    this.uniqueOrganizationId = uniqueOrganizationId;
}

public Long getNextAssetComponentDetailTemplateId() {
    return nextAssetComponentDetailTemplateId;
}

public void setNextAssetComponentDetailTemplateId(final Long nextAssetComponentDetailTemplateId) {
    this.nextAssetComponentDetailTemplateId = nextAssetComponentDetailTemplateId;
}

public String getUnit() {
    return unit;
}

public void setUnit(final String unit) {
    this.unit = unit;
}

public Tab getTab() {
    return tab;
}

public void setTab(final Tab tab) {
    this.tab = tab;
}

public Long getOrder() {
    return orderId;
}

public void setOrder(final Long order) {
    this.orderId = order;
}

public Boolean isMandatory() {
    return mandatory;
}

@Override
public String toString() {
    return name;
}

@Override
public boolean equals(final Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }

    final AssetComponentDetailTemplate that = (AssetComponentDetailTemplate) o;

    if (classNameId != null ? !classNameId.equals(that.classNameId) : that.classNameId != null) {
        return false;
    }
    if (dataType != that.dataType) {
        return false;
    }
    if (id != null ? !id.equals(that.id) : that.id != null) {
        return false;
    }
    if (name != null ? !name.equals(that.name) : that.name != null) {
        return false;
    }
    if (nextAssetComponentDetailTemplateId != null ?
        !nextAssetComponentDetailTemplateId.equals(that.nextAssetComponentDetailTemplateId) :
        that.nextAssetComponentDetailTemplateId != null) {
        return false;
    }
    if (orderId != null ? !orderId.equals(that.orderId) : that.orderId != null) {
        return false;
    }
    if (tab != that.tab) {
        return false;
    }
    if (uniqueOrganizationId != null ? !uniqueOrganizationId.equals(that.uniqueOrganizationId) :
        that.uniqueOrganizationId != null) {
        return false;
    }
    if (unit != null ? !unit.equals(that.unit) : that.unit != null) {
        return false;
    }

    return true;
}

@Override
public int hashCode() {
    int result = id != null ? id.hashCode() : 0;
    result = 31 * result + (name != null ? name.hashCode() : 0);
    result = 31 * result + (dataType != null ? dataType.hashCode() : 0);
    result = 31 * result + (classNameId != null ? classNameId.hashCode() : 0);
    result = 31 * result + (orderId != null ? orderId.hashCode() : 0);
    result = 31 * result +
             (nextAssetComponentDetailTemplateId != null ? nextAssetComponentDetailTemplateId.hashCode() : 0);
    result = 31 * result + (unit != null ? unit.hashCode() : 0);
    result = 31 * result + (tab != null ? tab.hashCode() : 0);
    result = 31 * result + (uniqueOrganizationId != null ? uniqueOrganizationId.hashCode() : 0);
    return result;
}
公共类AssetComponentDetailTemplate扩展了BaseEntite{
公共枚举数据类型{
TXT,
日期,
INT,
参加
列表
库勒斯,
参考文献
}
公共枚举选项卡{
同一,
本地化,
生命周期,
金融,,
研究,
细节
}
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@列(nullable=false)
私有字符串名称;
@列(nullable=false)
@枚举(EnumType.STRING)
私有数据类型数据类型;
私有整数classNameId;
私有长orderId;
私有长nextAssetComponentDetailTemplateId;
专用字符串单元;
@枚举(EnumType.STRING)
私人标签;
@列(nullable=false)
私人长唯一组织ID;
@OneToMany(fetch=FetchType.LAZY)
@JoinColumn(name=“idAssetComponentDetailTemplate”,可插入=false,可更新=false)
私有列表assetComponentDetailJoins;
私有布尔值强制=false;
公共资产组件详细信息模板(){
}
公共长getId(){
返回id;
}
公共无效集合id(最终长id){
this.id=id;
}
公共字符串getName(){
返回名称;
}
public void setName(最终字符串名){
this.name=名称;
}
公共数据类型getDataType(){
返回数据类型;
}
公共无效setDataType(最终数据类型DataType){
this.dataType=数据类型;
}
公共整数getClassNameId(){
返回classNameId;
}
public void setClassNameId(最终整数classNameId){
this.classNameId=classNameId;
}
公共长getUniqueOrganizationId(){
返回uniqueOrganizationId;
}
public void setUniqueOrganizationId(最终长uniqueOrganizationId){
this.uniqueOrganizationId=uniqueOrganizationId;
}
公共长getNextAssetComponentDetailTemplateId(){
返回nextasetComponentDetailTemplateId;
}
public void setNextAssetComponentDetailTemplateId(最后一个长的nextAssetComponentDetailTemplateId){
this.nextAssetComponentDetailTemplateId=nextAssetComponentDetailTemplateId;
}
公共字符串getUnit(){
返回单元;
}
公共无效集合单位(最终字符串单位){
这个。单位=单位;
}
公共选项卡getTab(){
返回选项卡;
}
公共无效设置选项卡(最终选项卡){
this.tab=tab;
}
公共长期订单(){
返回订单ID;
}
公共无效订单(最终长订单){
this.orderId=订单;
}
公共布尔值是强制性的(){
必须归还;
}
@凌驾
公共字符串toString(){
返回名称;
}
@凌驾
公共布尔等于(最终对象o){
if(this==o){
返回true;
}
如果(o==null | | getClass()!=o.getClass()){
返回false;
}
最终AssetComponentDetailTemplate=(AssetComponentDetailTemplate)o;
如果(classNameId!=null?!classNameId.equals(that.classNameId):that.classNameId!=null){
返回false;
}
if(数据类型!=该.dataType){
返回false;
}
如果(id!=null?!id.equals(that.id):that.id!=null){
返回false;
}
如果(name!=null?!name.equals(that.name):that.name!=null){
返回false;
}
如果(nextAssetComponentDetailTemplateId!=null?
!nextAssetComponentDetailTemplateId.equals(即.nextAssetComponentDetailTemplateId):
that.nextAssetComponentDetailTemplateId!=null){
返回false;
}
如果(orderId!=null?!orderId.equals(that.orderId):that.orderId!=null){
返回false;
}
如果(tab!=该.tab){
返回false;
}
如果(uniqueOrganizationId!=null?!uniqueOrganizationId.equals(that.uniqueOrganizationId):
that.uniqueOrganizationId!=null){
返回false;
}
如果(unit!=null?!unit.equals(that.unit):that.unit!=null){
返回false;
}
返回true;
}
@凌驾
公共整数
public class VerboseHashMap<K, V> implements Map<K, V> {

    private transient final static Logger logger = Logger.getLogger(VerboseHashMap.class);
    private HashMap<K, V> internalMap = new HashMap<K, V>();

    public boolean containsKey(Object o) {
        logger.debug("Object HashCode: " + o.hashCode());
        logger.debug("Map contents:");
        for (Entry<K, V> entry : internalMap.entrySet()) {
            logger.debug(entry.getKey().hashCode() + " - " + entry.getValue().toString());
        }
        return internalMap.containsKey(o);
    }

    public V get(Object key) {
        logger.debug("Object HashCode: " + key.hashCode());
        logger.debug("Map contents:");
        for (Entry<K, V> entry : internalMap.entrySet()) {
             logger.debug(entry.getKey().hashCode() + " - " + entry.getValue().toString());
        }
        return internalMap.get(key);
    }

}
public class Demo extends TestCase {

public void testMap() {

    Map<DomainObject, String> map = new HashMap<DomainObject, String>();
    DomainObject sb = new DomainObject();
    map.put(sb, "Some value");
    System.out.println(map.containsKey(sb));
    sb.value = "Some Text";
    System.out.println(map.containsKey(sb));

}

    private static class DomainObject {

        public String value = null;

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

    }

}
true 
false
class DomainObject {
    public String name;
    long hashCode() { return name.hashCode(); }
    boolean equals(Object other) { /* compare name in the two */'
}
   Map<DomainObject, Boolean> m = new HashMap<DomainObject, Boolean>();
   DomainObject do = new DomainObject(); 
   do.name = "ABC";
   m.put(do, true); // do goes in the map with hashCode of ABC
   do.name = "DEF";
   m.get(do);