equals()和hashCode()

  1. 原生equals()底层源码通过==来实现,比较的是两个对象(两个对象的引用地址)。
  2. hashCode()是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值.
  3. 两个对象的equals()相等(原生),hashCode()一定相等;
  4. 两个对象hashCode()相等,epuals()并不一定相等。

equals()

  1. 原生equals()底层源码通过==来实现,比较的是两个对象(两个对象的引用地址)。
  2. 重写equals()用来比较两个对象的内容是否相等。

常用覆盖逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* @desc 覆盖equals方法
*/
public boolean equals(Object obj){
if(obj == null){
return false;
}

//如果是同一个对象返回true,反之返回false
if(this == obj){
return true;
}

//判断是否类型相同
if(this.getClass() != obj.getClass()){
return false;
}
//比较对象属性值是否相等
//例如 Person中有两个属性 name,age
Person person = (Person)obj;
return name.equals(person.name) && age==person.age;
}

hashCode()

hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值.
hashFunction
对象的地址或者字符串或者数字就是keys,通过一个函数算出hash.

hashCode=F(key);

  1. hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置;
  2. 两个对象的equals()相等(原生),hashCode()一定相等;
  3. 两个对象hashCode()相等,epuals()并不一定相等。
  4. 我们应该根据对象的特点,重写hashCode方法,尽量避免(3)提到的哈希冲突情况。

HashSet判定一个对象是否重复:

HashSet判定为重复对象。

  1. 未重写equals()hashCode()时:
    code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Person p1 = new Person("aaa",1);
    Person p2 = p1;
    Person p3 = new Person("bbb",1);
    Set<Person> PS = Sets.newHashSet();
    PS.add(p1);
    PS.add(p2);
    PS.add(p3);
    System.out.println(p1.equals(p2));
    System.out.printf(PS+"====》"+"p1.hashCode(%s)==>p2.hashCode(%s)==>p3.hashCode(%s)",p1.hashCode(),p2.hashCode(),p3.hashCode());

    console:

    1
    2
    true
    [aaa - 1, bbb - 1]====》p1.hashCode(1047503754)==>p2.hashCode(1047503754)==>p3.hashCode(1722023916)

    我们知道原生equals()相等时,hashCode一定相等;
    code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Person p1 = new Person("aaa",1);
    Person p2 = new Person("aaa",1);
    Person p3 = new Person("bbb",1);
    Set<Person> PS = Sets.newHashSet();
    PS.add(p1);
    PS.add(p2);
    PS.add(p3);
    System.out.println(p1.equals(p2));
    System.out.printf(PS+"====》"+"p1.hashCode(%s)==>p2.hashCode(%s)==>p3.hashCode(%s)",p1.hashCode(),p2.hashCode(),p3.hashCode());

    console:

    1
    2
    false
    [bbb - 1, aaa - 1, aaa - 1]====》p1.hashCode(1047503754)==>p2.hashCode(1722023916)==>p3.hashCode(2009787198)
  2. 只重写hashCode()时:
    code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    private static class Person {
    @Override
    public int hashCode(){
    int nameHash = name.toUpperCase().hashCode();
    return nameHash ^ age;
    }
    }
    public static void main(String[] args){
    Person p1 = new Person("aaa",1);
    Person p2 = new Person("aaa",1);
    Person p3 = new Person("bbb",1);
    Set<Person> PS = Sets.newHashSet();
    PS.add(p1);
    PS.add(p2);
    PS.add(p3);
    System.out.println(p1.equals(p2));
    System.out.printf(PS+"====》"+"p1.hashCode(%s)==>p2.hashCode(%s)==>p3.hashCode(%s)",p1.hashCode(),p2.hashCode(),p3.hashCode());
    }

    console:

    1
    2
    false
    [aaa - 1, aaa - 1, bbb - 1]====》p1.hashCode(64544)==>p2.hashCode(64544)==>p3.hashCode(65539)
  3. 只重写equals()时:
    code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    private static class Person {
    @Override
    public boolean equals(Object obj){
    if(obj == null){
    return false;
    }

    //如果是同一个对象返回true,反之返回false
    if(this == obj){
    return true;
    }

    //判断是否类型相同
    if(this.getClass() != obj.getClass()){
    return false;
    }

    Person person = (Person)obj;
    return name.equals(person.name) && age==person.age;
    }
    }

    public static void main(String[] args){
    Person p1 = new Person("aaa",1);
    Person p2 = new Person("aaa",1);
    Person p3 = new Person("bbb",1);
    Set<Person> PS = Sets.newHashSet();
    PS.add(p1);
    PS.add(p2);
    PS.add(p3);
    System.out.println(p1.equals(p2));
    System.out.printf(PS+"====》"+"p1.hashCode(%s)==>p2.hashCode(%s)==>p3.hashCode(%s)",p1.hashCode(),p2.hashCode(),p3.hashCode());
    }

    console:

    1
    2
    true
    [bbb - 1, aaa - 1, aaa - 1]====》p1.hashCode(1047503754)==>p2.hashCode(1722023916)==>p3.hashCode(2009787198)
  4. 同时重写equals()hashCode()时:
    code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static void main(String[] args){
    Person p1 = new Person("aaa",1);
    Person p2 = new Person("aaa",1);
    Person p3 = new Person("bbb",1);
    Set<Person> PS = Sets.newHashSet();
    PS.add(p1);
    PS.add(p2);
    PS.add(p3);
    System.out.println(p1.equals(p2));
    System.out.printf(PS+"====》"+"p1.hashCode(%s)==>p2.hashCode(%s)==>p3.hashCode(%s)",p1.hashCode(),p2.hashCode(),p3.hashCode());
    }

    console:

    1
    2
    true
    [aaa - 1, bbb - 1]====》p1.hashCode(64544)==>p2.hashCode(64544)==>p3.hashCode(65539)

至此我们推断HashSet的判重逻辑是,hashCode()equals()同时满足