zoukankan      html  css  js  c++  java
  • hashCode与equals的区别与联系 .

     转:http://blog.csdn.net/afgasdg/article/details/6889383

    一、equals方法的作用

       1、默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。

    2 、要是类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等。

    没有覆盖equals方法代码如下:

     //学生类
    public class Student {
    private int age;
    private String name;

    public Student() {
    }
    public Student(int age, String name) {
    super();
    this.age = age;
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public String getName() {
    return name;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public void setName(String name) {
    this.name = name;
    }
    }

    测试 代码如下:

    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.Set;


    public class EqualsTest {
    public static void main(String[] args) {
    LinkedList<Student> list = new LinkedList<Student>();
    Set<Student> set = new HashSet<Student>();
    Student stu1  = new Student(3,"张三");
    Student stu2  = new Student(3,"张三");
    System.out.println("stu1 == stu2 : "+(stu1 == stu2));
    System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));
    list.add(stu1);
    list.add(stu2);
    System.out.println("list size:"+ list.size());

    set.add(stu1);
    set.add(stu2);
    System.out.println("set size:"+ set.size());
    }

    }


    运行结果:

    stu1 == stu2 : false
    stu1.equals(stu2) : false
    list size:2
    set size:2

    结果分析:Student类没有覆盖equals方法,stu1调用equals方法实际上调用的是Object的equals方法。所以采用对象内存地址是否相等来判断对象是否相等。因为是两个新对象所以对象的内存地址不相等,所以stu1.equals(stu2) 是false。

    3、我们覆盖一下equals方法(age和name属性),让Student类其通过判断对象的内容是否相等来确定对象是否相等。

    覆盖后的Student类:

    //学生类
    public class Student {
    private int age;
    private String name;

    public Student() {
    }
    public Student(int age, String name) {
    super();
    this.age = age;
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public String getName() {
    return name;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public void setName(String name) {
    this.name = name;
    }
    @Override
    public boolean equals(Object obj) {
    if (this == obj)
    return true;
    if (obj == null)
    return false;
    if (getClass() != obj.getClass())
    return false;
    Student other = (Student) obj;
    if (age != other.age)
    return false;
    if (name == null) {
    if (other.name != null)
    return false;
    } else if (!name.equals(other.name))
    return false;
    return true;
    }

    }


    运行结果:

    stu1 == stu2 : false
    stu1.equals(stu2) : true
    list size:2
    set size:2

    结果分析:因为Student两个对象的age和name属性相等,而且又是通过覆盖equals方法来判断的,所示stu1.equals(stu2) 为true。注意以上几次测试list和set的size都是2

    二、HashCode

    4、通过以上的代码运行,我们知道equals方法已经生效。接下来我们在覆盖一下hashCode方法(通过age和name属性来生成hashcode)并不覆盖equals方法,其中Hash码是通过age和name生成的。

    覆盖hashcode后的Student类:

    //学生类
    public class Student {
    private int age;
    private String name;

    public Student() {
    }
    public Student(int age, String name) {
    super();
    this.age = age;
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public String getName() {
    return name;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public void setName(String name) {
    this.name = name;
    }
    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
    }
    }


    运行结果:

    stu1 == stu2 : false
    stu1.equals(stu2) : false
    list size:2
    hashCode :775943
    hashCode :775943
    set size:2

    结果分析:我们并没有覆盖equals方法只覆盖了hashCode方法,两个对象虽然hashCode一样,但在将stu1和stu2放入set集合时由于equals方法比较的两个对象是false,所以就没有在比较两个对象的hashcode值。

    5、我们覆盖一下equals方法和hashCode方法。

    Student代码如下:

    //学生类
    public class Student {
    private int age;
    private String name;
    public Student() {
    }
    public Student(int age, String name) {
    super();
    this.age = age;
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public String getName() {
    return name;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public void setName(String name) {
    this.name = name;
    }
    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    System.out.println("hashCode : "+ result);
    return result;
    }
    @Override
    public boolean equals(Object obj) {
    if (this == obj)
    return true;
    if (obj == null)
    return false;
    if (getClass() != obj.getClass())
    return false;
    Student other = (Student) obj;
    if (age != other.age)
    return false;
    if (name == null) {
    if (other.name != null)
    return false;
    } else if (!name.equals(other.name))
    return false;
    return true;
    }

    }

     

    运行结果:

    
    
    

    stu1 == stu2 : false

    stu1.equals(stu2) :true

    list size:2

    hashCode :775943

    hashCode :775943

    set size:1

    结果分析:stu1和stu2通过equals方法比较相等,而且返回的hashCode值一样,所以放入set集合中时只放入了一个对象。

    6、下面我们让两个对象equals方法比较相等,但hashCode值不相等试试。

    Student类的代码如下:

    //学生类
    public class Student {
    private int age;
    private String name;
    private static int index=5;
    public Student() {
    }
    public Student(int age, String name) {
    super();
    this.age = age;
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public String getName() {
    return name;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public void setName(String name) {
    this.name = name;
    }
    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (age+index++);
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    System.out.println("result :"+result);
    return result;
    }
    @Override
    public boolean equals(Object obj) {
    if (this == obj)
    return true;
    if (obj == null)
    return false;
    if (getClass() != obj.getClass())
    return false;
    Student other = (Student) obj;
    if (age != other.age)
    return false;
    if (name == null) {
    if (other.name != null)
    return false;
    } else if (!name.equals(other.name))
    return false;
    return true;
    }

    }

    运行结果:

    stu1 == stu2 : false
    stu1.equals(stu2) : true
    list size:2
    hashCode :776098
    hashCode :776129
    set size:2

    结果分析:虽然stu1和stu2通过equals方法比较相等,但两个对象的hashcode的值并不相等,所以在将stu1和stu2放入set集合中时认为是两个不同的对象。

    7、修改stu1的某个属性值

    Student代码如下:

    //学生类
    public class Student {
    private int age;
    private String name;
    public Student() {
    }
    public Student(int age, String name) {
    super();
    this.age = age;
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public String getName() {
    return name;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public void setName(String name) {
    this.name = name;
    }
    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    System.out.println("hashCode : "+ result);
    return result;
    }
    @Override
    public boolean equals(Object obj) {
    if (this == obj)
    return true;
    if (obj == null)
    return false;
    if (getClass() != obj.getClass())
    return false;
    Student other = (Student) obj;
    if (age != other.age)
    return false;
    if (name == null) {
    if (other.name != null)
    return false;
    } else if (!name.equals(other.name))
    return false;
    return true;
    }

    }


    测试代码如下:

    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.Set;


    public class EqualsTest {
    public static void main(String[] args) {
    LinkedList<Student> list = new LinkedList<Student>();
    Set<Student> set = new HashSet<Student>();
    Student stu1  = new Student(3,"张三");
    Student stu2  = new Student(3,"张三");
    System.out.println("stu1 == stu2 : "+(stu1 == stu2));
    System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));
    list.add(stu1);
    list.add(stu2);
    System.out.println("list size:"+ list.size());

    set.add(stu1);
    set.add(stu2);
    System.out.println("set size:"+ set.size());
    stu1.setAge(34);
    System.out.println("remove stu1 : "+set.remove(stu1));
    System.out.println("set size:"+ set.size());
    }

    }


    运行结果:

    stu1 == stu2 : false
    stu1.equals(stu2) : true
    list size:2
    hashCode : 775943
    hashCode : 775943
    set size:1
    hashCode : 776904
    remove stu1 : false
    set size:1

    结果分析:

    当我们将某个对象存到set中时,如果该对象的属性参与了hashcode的计算,那么以后就不能修改该对象参与hashcode计算的那些属性了,否则会引起意向不到的错误的。正如测试中,不能够移除stu1对象。
    总结:

    1、equals方法用于比较对象的内容是否相等(覆盖以后)

    2、hashcode方法只有在集合中用到

    3、当覆盖了equals方法时,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否相等)。

    4、将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。

    5、将元素放入集合的流程图:


    6、HashSet中add方法源代码: 

    public boolean add(E e) {
    	return map.put(e, PRESENT)==null;
        }
    map.put源代码:
     public V put(K key, V value) {
            if (key == null)
                return putForNullKey(value);
            int hash = hash(key.hashCode());
            int i = indexFor(hash, table.length);
            for (Entry<K,V> e = table[i]; e != null; e = e.next) {
                Object k;
                if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                    V oldValue = e.value;
                    e.value = value;
                    e.recordAccess(this);
                    return oldValue;
                }
            }

            modCount++;
            addEntry(hash, key, value, i);
            return null;
        }
  • 相关阅读:
    237. Delete Node in a Linked List
    430. Flatten a Multilevel Doubly Linked List
    707. Design Linked List
    83. Remove Duplicates from Sorted List
    160. Intersection of Two Linked Lists
    426. Convert Binary Search Tree to Sorted Doubly Linked List
    142. Linked List Cycle II
    类之间的关系
    初始化块
    明确类和对象
  • 原文地址:https://www.cnblogs.com/wangle1001986/p/3577484.html
Copyright © 2011-2022 走看看