equal() and hashCode()方法

equal() and hashCode()方法

1. equal() 和hashCode()方法都是基类Object的方法

其源码如下:

 public boolean equals(Object obj) {
        return (this == obj);
    }

//hashCode method
/*Returns a hash code value for the object. This method is
  supported for the benefit of hash tables such as those provided by {@link java.util.HashMap}.*/

public native int hashCode();

因此,equal()方法就是直接比较对象的地址,对于hashCode(),Java采用了哈希表的原理。 哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。

2. 那么问题来了? 为什么重写equal()方法的时候通常需要重写hashCode()方法呢?

equal()方法是比较对象是否相等的,hashCode()方法是在当对象存入集合如HashSet对象,以及HashMap对象、HashTable等里面用的,这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。 如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了, 就调用它的equals方法与新元素进行比较,相同的话就覆盖,不相同就散列其它的地址。 所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。

比如String方法里重写了equal()方法:

//String重写的equal方法
  public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
//hashCode()方法
 public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

例子:

package com.demo;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class Equal {

    public static void main(String[] args) {
        Map<String,String> maps = new HashMap<String,String>();
        maps.put("1", "zhangsan");
        maps.put("1", "lisi");
        maps.put("2", "wangwu");
        maps.put("2", "zhaoliu");
        maps.put("3", "zhaoliu");

        Iterator<Map.Entry<String, String>> iterator = maps.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String, String> entry = iterator.next();
            System.out.println(entry.getKey()+entry.getValue());
        }
    }
}
//输出结果:
// 1lisi
// 2zhaoliu
// 3zhaoliu

3.总之
1、equal()是判断两个对象是否相同的
2、hashCode()是在HashSet、HashMap等中用的
3. 通常equal() 和hashCode()要保证对象的一致性。。。。

好的,让我来回答你的问题。当我们在实体类上使用@Embeddable和@IdClass注解实现复合主键时,我们可以重载equal()hashCode()方法来确保每个实体的主键值都是唯一的。下面是一个示例: 首先,在我们的实体类中,我们需要使用@Embeddable注解来注解我们的复合主键类。例如,我们有一个名为CustomerOrder的实体类,其中包含具有复合主键的OrderIdentity类。我们可以这样定义我们的OrderIdentity类: @Embeddable public class OrderIdentity implements Serializable { private Long customerId; private Long orderId; // Constructors, getters, and setters... @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof OrderIdentity)) return false; OrderIdentity that = (OrderIdentity) o; return Objects.equals(getCustomerId(), that.getCustomerId()) && Objects.equals(getOrderId(), that.getOrderId()); } @Override public int hashCode() { return Objects.hash(getCustomerId(), getOrderId()); } } 接下来,在我们的CustomerOrder实体类中,我们需要使用@IdClass注解来指定我们的复合主键类。 @IdClass(OrderIdentity.class) @Entity @Table(name = "customer_order") public class CustomerOrder implements Serializable { @Id @Column(name = "customer_id") private Long customerId; @Id @Column(name = "order_id") private Long orderId; // Other fields, constructors, getters, and setters... @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof CustomerOrder)) return false; CustomerOrder that = (CustomerOrder) o; return Objects.equals(getCustomerId(), that.getCustomerId()) && Objects.equals(getOrderId(), that.getOrderId()); } @Override public int hashCode() { return Objects.hash(getCustomerId(), getOrderId()); } } 如您所见,在OrderIdentity类和CustomerOrder类中,我们都重载了equals()hashCode()方法,并使用了Objects.equals()和Objects.hash()方法来确保复合主键中的每个属性都被考虑在内。这样,我们就可以保证每个实体的主键值都是唯一的。 希望这个例子可以帮助您理解如何在实体类上使用@Embeddable和@IdClass注解实现复合主键,并确保每个实体的主键值都是唯一的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值