`
sundongyadh
  • 浏览: 20106 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java复合主键 以及 重写hashCode 和 equals

阅读更多

使用主键的情况一般是 当缓存一组数据,而该数据中一个字段无法做到唯一性,So 声明个对象,将多个字段组合起来,作为缓存KEY。

 

如果该缓存使用 HashMap  实现;

考虑到HashMap 里存储N个对象后。 利用对象KEY直接取对应的值,我们会获取不到对应的值。

 

这就关系HashMap 内部 get(Key)获取机制了,里面是先获取 该Key 的hashCode() ,而后计算出Hash码,

再去获取对应对象的索引,找到该对象后,对比Hash码是否相等 以及 Equals 当前Key ,与 HashMap内对应的Key ,是否相等,对象与对象比较不是简单的值与值 结果:false。

 

那么基于以上情况.我们就有必要 重写 该Key 对象的 hashCode 和 equals 方法。

使得它们的 HashCode 和 equals 都相等。

 

使用Eclipse IDE 内就有自动生成机制

右键类编辑器 --> Source --> Generate hashCode() and equals()

 

PS:

HashMap源码 --> 构造函数

int loadFactor = 0.75;

this.loadFactor = loadFactor; //加载系数因子
threshold = (int)(capacity * loadFactor);  //初始容量*系数因子

容器内部每当容量达到threshold 后将自动*2增长容量?貌似。

 

1.两个对象equals相等那么hashcode 是一定相等的。

2.两个对象equals不相等hashcode可能相等可以不相等。

因为hashCode说白了是地址值经过一系列的复杂运算得到的结果,而Object中的equals方法底层比较的就是地址值,所以equals()相等,hashCode必定相等,反equals()不等,在java底层进行哈希运算的时候有一定的几率出现相等的hashCode,所以hashCode()可等可不等。

 

public class SunDy {
	
	public SunDy(){}
	
	public SunDy(Integer id,Integer age){
		this.id = id;
		this.age = age;
	}
	
	private Integer id;
	
	private Integer age;
	
	/**
	 * prime = 31 ; 为什么使用31?  :
	 * 选择31原因是因为31是一个素数,存储数据计算hash地址的时候,我们希望尽量减少有同样的hash地址,所谓“冲突”。
	 * 如果使用相同hash地址的数据过多,那么这些数据所组成的
	 * hash链就更长,从而降低了查询效率!所以在选择系数的时候要选择尽量长的系数并且让乘法尽量不要溢出的系数,
	 * 因为如果计算出来的hash地址越大,所 谓的“冲突”就越少,查找起来效率也会提高.
	 * 31可以 由i*31== (i<<5)-1来表示,现在很多虚拟机里面都有做相关优化,使用31的原因可能是为了更好的分配hash地址,并且31只占用5bits!
	 * 在java乘法中如果数字相乘过大会导致溢出的问题,从而导致数据的丢失.
	 * 而31则是素数(质数)而且不是很长的数字,最终它被选择为相乘的系数的原因不过与此.
	 * PS: 隐隐记得那篇博客也提到过,是为了不让它为负数?
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((age == null) ? 0 : age.hashCode());
		result = prime * result + ((id == null) ? 0 : id.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;
		SunDy other = (SunDy) obj;
		if (age == null) {
			if (other.age != null)
				return false;
		} else if (!age.equals(other.age))
			return false;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
	
	
	
}

 

 

 

 

   另外网上搜索其他博文讲的比较细致的有:

  1.Java 中正确使用 hashCode 和 equals 方法    [ or http://www.oschina.net/question/82993_75533]

   2.关于java HashCode 内使用31系数问题

 

 

 

 

 

分享到:
评论

相关推荐

    Spring Data Jpa 复合主键的实现

    Spring Data Jpa 复合主键的实现需要使用 @IdClass 注解来标注复合主键类,并且需要在复合主键类中重写 hashCode 和 equals 方法。这样,我们就可以正确地使用复合主键来唯一标识数据表中的记录。

    复合主键@IdClass

    equals方法用于比较两个复合主键对象是否相等,而hashCode方法则用于生成对象的哈希值,这对于实体管理尤其重要,因为实体管理器在执行find等操作时会依赖这些方法。 下面是一个具体的复合主键类示例——`...

    Hibernate中对数据库复合主键的支持.pdf

    2. **重写equals和hashCode方法**:这两个方法对于判断实体对象是否相等以及在集合中存储实体至关重要。在使用复合主键的情况下,通常会基于所有构成主键的属性来重写这些方法。 针对`Person`类的实现,我们可以...

    Hibernate复合主键

    为了保证复合主键的唯一性,还需要重写`equals()`和`hashCode()`方法。 ##### 2. 配置复合主键 在Hibernate映射文件`TUser.hbm.xml`中配置复合主键: ```xml &lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/...

    hibernate3 注释生成复合主键或者嵌入式主键的方法及实例.doc

    此外,为了确保两个`UserRolePK`对象是否相等,我们需要重写`equals()`和`hashCode()`方法。这里,`equals()`方法主要比较`userId`和`roleId`的值是否相等,而`hashCode()`方法则应返回基于这两个属性计算出的哈希码...

    使用@IdClass创建联合主键,并实现外部关联

    首先,我们需要创建一个BuildUnionPkId类,实现Serializable接口,并重写hashCode和equals方法。 ```java public class BuildUnionPkId implements Serializable { private static final long serialVersionUID = ...

    hibernat非常有用的学习文档

    在 Hibernate 中,可以通过创建一个独立的主键类来表示复合主键,这个类需要实现 `Serializable` 接口,并重写 `equals()` 和 `hashcode()` 方法。在映射文件中,使用 `&lt;composite-id&gt;` 标签来指定主键类,然后通过 ...

    Hibernate参考文档

    ##### 4.3 实现 equals() 和 hashCode() 为了正确地比较实体对象和利用缓存机制,实体类需要重写这两个方法。 ##### 4.4 动态模型 允许在运行时动态创建和修改实体类。 ##### 4.5 元组片断映射 用于定制化地...

    Hibernate知识总结

    - 可通过 `@Embeddable`、`@EmbeddedId`、`@IdClass` 或 XML 配置的 `&lt;composite-id&gt;` 来定义复合主键,组件类需实现 `Serializable` 并重写 `equals()` 和 `hashCode()` 方法。 9. **对象状态**: - Transient: ...

    POJOGenerator v1.3.3 Install(可视化POJO代码生成器最终版)

    知档,其中,ID列名默认使用主键名称(若为复合主键则采用次序排首位的主键列名) ,而Oracle环境下的sequence对象名称则为“seq_表名_id”格式的默认名称,请根据 实际情况修改。该配置档用于CmSdk4j-Core框架的ORM...

    hibernate 帮助文档

    - **composite-id**:定义复合主键的映射。 - **鉴别器(discriminator)**:配置鉴别器来支持继承。 - **版本(version)**:配置版本字段以支持并发控制。 - **timestamp**:使用时间戳字段来支持并发控制。 - **...

    hibernate教程

    - **实体比较**:为了确保实体对象的正确比较,必须重写 `equals()` 和 `hashCode()` 方法。 ##### 4.4 生命周期回调 - **生命周期事件**:支持多种生命周期事件,如 `preInsert`、`postLoad` 等。 ##### 4.5 ...

    Hibernate Reference Documentation(Hibernate参考手册)

    ##### 3.3 `equals()` 和 `hashCode()` 实现 - 为了正确地比较实体对象以及提高缓存效率,实体类需要重写这两个方法。 ##### 3.4 生命周期回调 - Hibernate支持生命周期事件回调,如`prePersist`、`postPersist`...

    Java学习笔记-个人整理的

    {1.8.1.3}复合赋值运算}{28}{subsubsection.1.8.1.3} {1.8.2}逻辑运算}{29}{subsection.1.8.2} {1.8.3}条件运算符}{29}{subsection.1.8.3} {1.8.4}移位运算符}{30}{subsection.1.8.4} {1.9}流程控制}{31}{...

Global site tag (gtag.js) - Google Analytics