hashcode()与equals

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

一、equals方法的作用

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

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

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

[java] view plaincopy

  1. //学生类

  2. public class Student {

  3. private int age;

  4. private String name;
  5. public Student() {

  6. }

  7. public Student(int age, String name) {

  8. super();

  9. this.age = age;

  10. this.name = name;

  11. }

  12. public int getAge() {

  13. return age;

  14. }

  15. public String getName() {

  16. return name;

  17. }

  18. public void setAge(int age) {

  19. this.age = age;

  20. }

  21. public void setName(String name) {

  22. this.name = name;

  23. }

  24. }

测试 代码如下:

[java] view plaincopy

  1. import java.util.HashSet;

  2. import java.util.LinkedList;

  3. import java.util.Set;
  4. public class EqualsTest {

  5. public static void main(String[] args) {

  6. LinkedList<Student> list = new LinkedList<Student>();

  7. Set<Student> set = new HashSet<Student>();

  8. Student stu1  = new Student(3,"张三");

  9. Student stu2  = new Student(3,"张三");

  10. System.out.println("stu1 == stu2 : "+(stu1 == stu2));

  11. System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));

  12. list.add(stu1);

  13. list.add(stu2);

  14. System.out.println("list size:"+ list.size());
  15. set.add(stu1);

  16. set.add(stu2);

  17. System.out.println("set size:"+ set.size());

  18. }
  19. }

运行结果:

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类:

[java] view plaincopy

  1. //学生类

  2. public class Student {

  3. private int age;

  4. private String name;
  5. public Student() {

  6. }

  7. public Student(int age, String name) {

  8. super();

  9. this.age = age;

  10. this.name = name;

  11. }

  12. public int getAge() {

  13. return age;

  14. }

  15. public String getName() {

  16. return name;

  17. }

  18. public void setAge(int age) {

  19. this.age = age;

  20. }

  21. public void setName(String name) {

  22. this.name = name;

  23. }

  24. @Override

  25. public boolean equals(Object obj) {

  26. if (this == obj)

  27. return true;

  28. if (obj == null)

  29. return false;

  30. if (getClass() != obj.getClass())

  31. return false;

  32. Student other = (Student) obj;

  33. if (age != other.age)

  34. return false;

  35. if (name == null) {

  36. if (other.name != null)

  37. return false;

  38. } else if (!name.equals(other.name))

  39. return false;

  40. return true;

  41. }
  42. }

运行结果:

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类:

[java] view plaincopy

  1. //学生类

  2. public class Student {

  3. private int age;

  4. private String name;
  5. public Student() {

  6. }

  7. public Student(int age, String name) {

  8. super();

  9. this.age = age;

  10. this.name = name;

  11. }

  12. public int getAge() {

  13. return age;

  14. }

  15. public String getName() {

  16. return name;

  17. }

  18. public void setAge(int age) {

  19. this.age = age;

  20. }

  21. public void setName(String name) {

  22. this.name = name;

  23. }

  24. @Override

  25. public int hashCode() {

  26. final int prime = 31;

  27. int result = 1;

  28. result = prime * result + age;

  29. result = prime * result + ((name == null) ? 0 : name.hashCode());

  30. return result;

  31. }

  32. }

运行结果:

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代码如下:

[java] view plaincopy

  1. //学生类

  2. public class Student {

  3. private int age;

  4. private String name;

  5. public Student() {

  6. }

  7. public Student(int age, String name) {

  8. super();

  9. this.age = age;

  10. this.name = name;

  11. }

  12. public int getAge() {

  13. return age;

  14. }

  15. public String getName() {

  16. return name;

  17. }

  18. public void setAge(int age) {

  19. this.age = age;

  20. }

  21. public void setName(String name) {

  22. this.name = name;

  23. }

  24. @Override

  25. public int hashCode() {

  26. final int prime = 31;

  27. int result = 1;

  28. result = prime * result + age;

  29. result = prime * result + ((name == null) ? 0 : name.hashCode());

  30. System.out.println("hashCode : "+ result);

  31. return result;

  32. }

  33. @Override

  34. public boolean equals(Object obj) {

  35. if (this == obj)

  36. return true;

  37. if (obj == null)

  38. return false;

  39. if (getClass() != obj.getClass())

  40. return false;

  41. Student other = (Student) obj;

  42. if (age != other.age)

  43. return false;

  44. if (name == null) {

  45. if (other.name != null)

  46. return false;

  47. } else if (!name.equals(other.name))

  48. return false;

  49. return true;

  50. }
  51. }

运行结果:

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类的代码如下:

[java] view plaincopy

  1. //学生类

  2. public class Student {

  3. private int age;

  4. private String name;

  5. <span style="color:#ff0000;">private static int index=5;</span>

  6. public Student() {

  7. }

  8. public Student(int age, String name) {

  9. super();

  10. this.age = age;

  11. this.name = name;

  12. }

  13. public int getAge() {

  14. return age;

  15. }

  16. public String getName() {

  17. return name;

  18. }

  19. public void setAge(int age) {

  20. this.age = age;

  21. }

  22. public void setName(String name) {

  23. this.name = name;

  24. }

  25. @Override

  26. public int hashCode() {

  27. final int prime = 31;

  28. int result = 1;

  29. result = prime * result + <span style="color:#ff0000;">(age+index++)</span>;

  30. result = prime * result + ((name == null) ? 0 : name.hashCode());

  31. <span style="color:#ff0000;">System.out.println("result :"+result);</span>

  32. return result;

  33. }

  34. @Override

  35. public boolean equals(Object obj) {

  36. if (this == obj)

  37. return true;

  38. if (obj == null)

  39. return false;

  40. if (getClass() != obj.getClass())

  41. return false;

  42. Student other = (Student) obj;

  43. if (age != other.age)

  44. return false;

  45. if (name == null) {

  46. if (other.name != null)

  47. return false;

  48. } else if (!name.equals(other.name))

  49. return false;

  50. return true;

  51. }
  52. }

运行结果:

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代码如下:

[java] view plaincopy

  1. //学生类

  2. public class Student {

  3. private int age;

  4. private String name;

  5. public Student() {

  6. }

  7. public Student(int age, String name) {

  8. super();

  9. this.age = age;

  10. this.name = name;

  11. }

  12. public int getAge() {

  13. return age;

  14. }

  15. public String getName() {

  16. return name;

  17. }

  18. public void setAge(int age) {

  19. this.age = age;

  20. }

  21. public void setName(String name) {

  22. this.name = name;

  23. }

  24. @Override

  25. public int hashCode() {

  26. final int prime = 31;

  27. int result = 1;

  28. result = prime * result + age;

  29. result = prime * result + ((name == null) ? 0 : name.hashCode());

  30. System.out.println("hashCode : "+ result);

  31. return result;

  32. }

  33. @Override

  34. public boolean equals(Object obj) {

  35. if (this == obj)

  36. return true;

  37. if (obj == null)

  38. return false;

  39. if (getClass() != obj.getClass())

  40. return false;

  41. Student other = (Student) obj;

  42. if (age != other.age)

  43. return false;

  44. if (name == null) {

  45. if (other.name != null)

  46. return false;

  47. } else if (!name.equals(other.name))

  48. return false;

  49. return true;

  50. }
  51. }

测试代码如下:

[java] view plaincopy

  1. import java.util.HashSet;

  2. import java.util.LinkedList;

  3. import java.util.Set;
  4. public class EqualsTest {

  5. public static void main(String[] args) {

  6. LinkedList<Student> list = new LinkedList<Student>();

  7. Set<Student> set = new HashSet<Student>();

  8. Student stu1  = new Student(3,"张三");

  9. Student stu2  = new Student(3,"张三");

  10. System.out.println("stu1 == stu2 : "+(stu1 == stu2));

  11. System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));

  12. list.add(stu1);

  13. list.add(stu2);

  14. System.out.println("list size:"+ list.size());
  15. set.add(stu1);

  16. set.add(stu2);

  17. System.out.println("set size:"+ set.size());

  18. stu1.setAge(34);

  19. System.out.println("remove stu1 : "+set.remove(stu1));

  20. System.out.println("set size:"+ set.size());

  21. }
  22. }

运行结果:

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方法源代码:

[java] view plaincopy

  1. public boolean add(E e) {

  2. return map.put(e, PRESENT)==null;

  3. }

map.put源代码:

[java] view plaincopy

    1. <pre name="code" class="java"> public V put(K key, V value) {

    2. if (key == null)

    3. return putForNullKey(value);

    4. int hash = hash(key.hashCode());

    5. int i = indexFor(hash, table.length);

    6. for (Entry<K,V> e = table[i]; e != null; e = e.next) {

    7. Object k;

    8. if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

    9. V oldValue = e.value;

    10. e.value = value;

    11. e.recordAccess(this);

    12. return oldValue;

    13. }

    14. }
    15. modCount++;

    16. addEntry(hash, key, value, i);

    17. return null;

    18. }</pre>

    19. <pre></pre>

    20. <pre></pre>

hashcode()与equals

时间: 2024-10-14 00:46:59

hashcode()与equals的相关文章

hashcode和equals

在java中,万物皆对象,所有的对象都继承于Object类,Object类有两个方法equals和hashCode.equals一般用来比较两个对象的内容是否相等,而hashCode一般用来提高容器的查询效率. public native int hashCode(); public boolean equals(Object obj) { return (this == obj); } equals在没有重写的情况下和==是一样的,对于值类型,比较的是值,对于引用类型则比较的是对象的首地址.

hashCode与equals

很多东西都是大处显积累,小处见功力,来点功力. hashCode跟equals 相伴相生,所以要一起讨论才有意义. 在java中,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,就是说当集合中插入对象时,怎么分辨该对象是否已经存在.按照正常思路,应该是依次进行equals比较,但是其实效率不高,java中的做法是先比较hashCode,如果相同在equals比较,到这里,疑问就出来了,为什么会比较hashCode,hashCode相同的情况下为什么equals为什么还会不同?

Object对象详解(三)之hashCode与equals

从学习Java开始,就从各个师兄.各种书籍.各大网站听到.看到,重写equals方法必须重写hashCode方法.重写equals方法必须重写hashCode方法.重写equals方法必须重写hashCode方法. 那么为什么呢?今天就详细剖析一下equals和hashCode! equals方法是比较两个对象实例是否相等.Object中equals方法的描述为: public boolean equals(Object obj) { return (this == obj); } 也就是默认情

重写hashCode与equals方法的作用

为了阐明其作用,我们先来假设有如下一个Person类. class Person { public Person(String name, int age) { this.name = name; this.age = age; } private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; }

java 小结3 hashcode和equals I/o问题

我需要把星期天看的一些东西记录下来,要不然会忘记. hashCode.equals: 1)每个java对象都有hashCode和equals方法. java的终极类是object类,那么object类是如何来标注自己呢,就是object这个类是如何来区分对方.就是使用它们的hashcode和equals来推断. (hashcode是通过hash算法实现的) 2)JVM每new一个object,都会讲Object丢到一个Hash(哈希表)里去,这样下次比较或者获取这个对象的时候就可以根据对象的ha

key的hashcode与equals方法改写

get方法过程:首先计算key的hashcode,找到数组中对应位置的某一元素,然后通过key的equeals方法在对应的链表中找到需要的元素.所以,hashcode与equals方法对于找到对应元素是两个关键的方法. HsahMap的key可以是任何类型,例如User对象,为了保证两个具有相同属性的User对象的hashcode相同,我们需要改写hashcode方法,比方说把hashcode的值的计算与User对象的id关联起来,那么只要user对象拥有相同的id,那么他们的hashcode就

Java基础:hashCode与equals个人学习记录

摘要: 本文主要记录本人对hashCode和对equals两个知识点的学习过程. 从学生时期初学java,就知道hashCode和equals这两个方法,工作中equals方法使用也是特别频繁,要说equals方法,那么必须少不了hashCode这个方法.下面就整理一下本人目前对这俩方法的理解,文中如有错误,请指正,多谢. hash code(散列码,也可以叫哈希码值)是对象产生的一个整型值.其生成没有规律的.二者散列码可以获取对象中的信息,转成那个对象的"相对唯一"的整型值.所有对象

hashcode和equals方法

分析: 1:Person类 1:姓名和年龄 2:重写hashCode和equals方法 1:如果不重写,调用Object类的equals方法,判断内存地址,为false 1:如果是Person类对象,并且姓名和年龄相同就返回true 2:如果不重写,调用父类hashCode方法 1:如果equals方法相同,那么hashCode也要相同,需要重写hashCode方法 3:重写toString方法 1:不重写,直接调用Object类的toString方法,打印该对象的内存地址 Person类 cl

Java hashCode() 和 equals()的若干问题

原文:http://www.cnblogs.com/skywang12345/p/3324958.html 本章的内容主要解决下面几个问题: 1 equals() 的作用是什么? 2 equals() 与 == 的区别是什么? 3 hashCode() 的作用是什么? 4 hashCode() 和 equals() 之间有什么联系? 第1部分 equals() 的作用 equals() 的作用是 用来判断两个对象是否相等. equals() 定义在JDK的Object.java中.通过判断两个对

Java 中 hashCode 和 equals 方法 小结

转载:http://www.oschina.net/question/82993_75533 hashCode()和equals()定义在Object类中,这个类是所有java类的基类,所以所有的java类都继承这两个方法. hashcode主要是set集合使用,是用于判断对象是否”可能“相等的快捷办法,以解决大集合的问题.举例来说,如果一个一万个元素的集合加入一个元素,如果是一个新元素,那么必须要equal一万次才能加入.所以采用hashcode,hashcode的思路是如果equal,则ha