黑马程序员技术交流社区

标题: 帮我解读hashcode()和equals() [打印本页]

作者: @白纸嘿字@    时间: 2015-9-30 01:14
标题: 帮我解读hashcode()和equals()
HashMapDemo
  1. package com.itheima.Map;

  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.Set;

  5. import com.itheima.domain.Employe;

  6. public class HashMapDemo {

  7.         /**
  8.          * @param args
  9.          * 练习:
  10.          * 将员工和户口所在地存储到HashMap"容器"。
  11.          * 要求:
  12.          * 同姓名,同年龄,视为同一个员工。按照年龄从小到大的顺序,对员工进行排序
  13.          *
  14.          * 分析:
  15.          * 1、定义一个员工类,包含姓名,年龄等
  16.          * 2、员工和户口所在地是一种映射关系
  17.          */
  18.         public static void main(String[] args) {
  19.                 /*
  20.                  * 建立HashMap"容器"。
  21.                  */
  22.                 Map<Employe,String> map=new HashMap<Employe, String>();
  23.                 /*
  24.                  * 存储HashMap"容器"元素
  25.                  */
  26.                 map.put(new Employe("xiaoqiang",18), "beijing");
  27.                 map.put(new Employe("wangqiang",28), "tianjin");
  28.                 map.put(new Employe("chenqiang",36), "shanghai");
  29.                 /*
  30.                  * 获取Map“容器”元素
  31.                  */
  32.                 Set<Employe> keySet=map.keySet();
  33.                 for (Employe employe : keySet) {
  34.                         String value=map.get(employe);
  35.                         System.out.println(employe.getName()+":"+employe.getAge()+"........"+value);
  36.                 }
  37.         }

  38. }
复制代码

Employe
  1. package com.itheima.domain;

  2. public class Employe {
  3.         private String name;
  4.         private int age;
  5.        
  6.         public Employe() {
  7.                 super();
  8.                
  9.         }
  10.        
  11.         public Employe(String name, int age) {
  12.                 super();
  13.                 this.name = name;
  14.                 this.age = age;
  15.         }

  16.         public String getName() {
  17.                 return name;
  18.         }
  19.         public void setName(String name) {
  20.                 this.name = name;
  21.         }
  22.         public int getAge() {
  23.                 return age;
  24.         }
  25.         public void setAge(int age) {
  26.                 this.age = age;
  27.         }

  28.         @Override
  29.         public String toString() {
  30.                 return "Employe [name=" + name + ", age=" + age + "]";
  31.         }

  32.         @Override
  33.         public int hashCode() {
  34.                 final int prime = 31;
  35.                 int result = 1;
  36.                 result = prime * result + age;
  37.                 result = prime * result + ((name == null) ? 0 : name.hashCode());
  38.                 return result;
  39.         }

  40.         @Override
  41.         public boolean equals(Object obj) {
  42.                 if (this == obj)
  43.                         return true;
  44.                 if (obj == null)
  45.                         return false;
  46.                 if (getClass() != obj.getClass())
  47.                         return false;
  48.                 Employe other = (Employe) obj;
  49.                 if (age != other.age)
  50.                         return false;
  51.                 if (name == null) {
  52.                         if (other.name != null)
  53.                                 return false;
  54.                 } else if (!name.equals(other.name))
  55.                         return false;
  56.                 return true;
  57.         }
  58.        
  59.        
  60. }
复制代码

这个怎么就实现了“按照年龄从小到大排序”,我知道这“文章”在hashcode()和equals(),所以能不能帮我解读一下,这个两个方法中的代码是什么意思?


作者: kangyang    时间: 2015-9-30 09:35
这是equal的源码,应该很好懂吧~~
  1.     public boolean equals(Object anObject) {
  2.         if (this == anObject) {
  3.             return true;
  4.         }
  5.         if (anObject instanceof String) {
  6.             String anotherString = (String)anObject;
  7.             int n = count;
  8.             if (n == anotherString.count) {
  9.                 char v1[] = value;
  10.                 char v2[] = anotherString.value;
  11.                 int i = offset;
  12.                 int j = anotherString.offset;
  13.                 while (n-- != 0) {
  14.                     if (v1[i++] != v2[j++])
  15.                         return false;
  16.                 }
  17.                 return true;
  18.             }
  19.         }
  20.         return false;
  21.     }
复制代码

equal就是:1、当用==判断为true时返回true
                   2、否则就判定是否为String类型,如果是接着判定你所给的两个字符串所对应的字符是否相等,是                      就返回true,否则返回false。
作者: kangyang    时间: 2015-9-30 09:47
对于,hashcode()我不是很懂,不过貌似是通过hashcode()方法当一个中间桥梁进行比较。在api中hashcode()方法描述为“返回此属性集的哈希码值”。我想应该是先通过hashcode()方法将不同对象转化为相对应的hash码值,然后通过对比hash码值是否相同来判定不同对象是否相等的。
作者: 只求不悔    时间: 2015-9-30 09:50
好难,,貌似我不懂的样子
作者: tianweidong    时间: 2015-9-30 10:05
      我觉得你应该用TreeMap实现,TreeMap可以将存入的对象排序,不过对象实现类要实现comparable接口或在TreeMap中传入比较器,来实现其可比性
     hashMap不能实现排序
作者: caiyao    时间: 2015-9-30 18:59
hashcode比较大小是先比较哈希值,如果哈希值相同就比较equals,不同则不存则不用再比较equals了。集合一般都是用hashcode()保证集合元素的唯一性的
作者: 香港胖仔    时间: 2015-9-30 19:26
对用treemap实现comparator接口 然后在compare方法中return this.age-age
作者: IT黑马_梧桐    时间: 2015-9-30 20:35
纯手打,希望楼主能够给分

QQ截图20150930203252.jpg (154.19 KB, 下载次数: 89)

QQ截图20150930203252.jpg

QQ截图20150930203305.jpg (162.83 KB, 下载次数: 75)

QQ截图20150930203305.jpg

作者: IT黑马_梧桐    时间: 2015-9-30 20:36
IT黑马_梧桐 发表于 2015-9-30 20:35
纯手打,希望楼主能够给分

那个age=2,name=8;age=4,name=6;手误,希望见谅
作者: 15001162522    时间: 2015-10-1 18:42
楼主,求问你那种带行数的发帖格式是咋弄的?我在写博客需要使用这种格式~~~小菜鸟一枚,求告知
作者: liudongcan    时间: 2015-10-1 18:50
HashMap没法排序,只能保证元素唯一,用TreeMap吧
作者: 穆帆    时间: 2015-10-2 12:22
记住,需要比较就用Treeset,然后用比较器去排序,先按年龄排,年龄相同的话就按姓名排
作者: @白纸嘿字@    时间: 2015-10-2 21:05
caiyao 发表于 2015-9-30 18:59
hashcode比较大小是先比较哈希值,如果哈希值相同就比较equals,不同则不存则不用再比较equals了。集合一般 ...

发这个帖子,是想搞懂hashcode()和equals()中每一句代码的意思!so,能不能拆分解读一下{:2_43:}
作者: @白纸嘿字@    时间: 2015-10-2 22:43
本帖最后由 @白纸嘿字@ 于 2015-10-2 23:18 编辑
IT黑马_梧桐 发表于 2015-9-30 20:35
纯手打,希望楼主能够给分
看不懂!?

关于hashCode():
“String=8”,name==null,返回值就是flase,就会执行name.hashCode()——String类的hashCode(),返回一个哈希值;“String=6”,也是这样。r然后,它们各自和前面的值相加,最后的结果是相等的?
这又涉及到了String类的hashCode(),“8”和“6”在String类的hashCode()中算出来的哈希值是多少,是怎么得出来的啊?

关于equals():
是因为hashCode()相等了,才去调用equals()的,为什么还要重复比较!
作者: @白纸嘿字@    时间: 2015-10-2 23:20
15001162522 发表于 2015-10-1 18:42
楼主,求问你那种带行数的发帖格式是咋弄的?我在写博客需要使用这种格式~~~小菜鸟一枚,求告知 ...

我就是直接粘贴的
作者: 15001162522    时间: 2015-10-2 23:33
@白纸嘿字@ 发表于 2015-10-2 23:20
我就是直接粘贴的

哦哦 我已经会了 嘿嘿
作者: @白纸嘿字@    时间: 2015-10-3 09:43
15001162522 发表于 2015-10-2 23:33
哦哦 我已经会了 嘿嘿

就是直接粘贴吧!
作者: 15001162522    时间: 2015-10-3 10:24
@白纸嘿字@ 发表于 2015-10-3 09:43
就是直接粘贴吧!

是的呢
作者: Rzzz    时间: 2015-10-6 23:41
看了楼主的代码中,你哪里能实现排序呀?就能实现个遍历输出呀..用的是KeySet方法..返回一个键的set子类对象集合..然后遍历键获取对应的值.......在HashMap我们说的无序是指不能按我们存入的顺序输出原数据.. HashMap本身就不能保证集合排序..你要做到排序就定义TreeMap  在定义的时候用匿名内部类,去实现Comparator接口去从写里面的compare方法.
.(new Comparator<Student>() {
                        @Override
                        public int compare(Student s1, Student s2) {
                               int  num=s2.getAge() - s1.getAge()   //第一按照年龄比较
                                return num == 0 ? s1.getName().compareTo(s2.getName()) : num; //第二按照姓名比较
                        }
                });

第一:这种匿名内部适合我们只对这个抽象方法调用一次,然后后面就不在使用,适合用匿名类.

第二:就是你在员工类里面重写Hashcode和equals()方法.保障是否是同一个对象..这里是要考虑存储的问题...还有从写ComparTo方法,重写你要按照一个什么顺序去排序



开发中习惯用第一种,一般在实现这个功能的时候我们也习惯采用匿名内部类去实现排序.

作者: 蓝天I    时间: 2015-10-7 17:09
hashcode()方法和equals()方法一般用于判断对象是否是同一个对象。
在类中重写hashCode()和equals()方法,是为了确定对象的唯一性,首先,该类被保存时,系统会调用类的hashCode()方法,来得到它的哈希码值,如果值不同,则是同一个对象;如果哈希码值相同,系统会调用该类的equals()方法,来判断类中的每一个属性的类容是否相同,若都相同则可看做同一个对象,否则为不同对象。
作者: didixyy    时间: 2015-10-9 14:28
是这样的,map集合本身拥有自然排序的功能,排序是根据对象的HASH值来排序的,因为对象每一个对象都有hashCode的方法,这个方法是继承与Object类的,但是你的Employe对象重写了hashCode方法,所以这时候对象的HASH值是你的方法自己设定的,当集合里存在2个HASH值相同的情况的时候,MAP集合的机制会去调用对象本身的equals方法,来比较出谁先谁后。这是调用的是对象的equals方法,这里你又重写了equals方法,你自己定义的equals方法就是进行年龄的比较。就实现了“按照年龄从小到大排序”。
作者: 雨来    时间: 2015-10-13 15:26
1、equals方法用于比较对象的内容是否相等(覆盖以后)
2、hashcode方法只有在集合中用到
3、当覆盖了equals方法时,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否等)。
4、将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入
作者: 15555566103    时间: 2015-10-19 19:50
理解就行了,但要回用,不要挖掘的太深,太深的东西,就算现在记住了,短时间内不用,也会忘了的
作者: 朦胧色彩    时间: 2015-10-26 08:45
当往HashMap集合里添加元素的时候,首先是执行hashCode方法,获取存入该键值对的位置,然后如果该位置没有其他键值对占用,那么直接存在这个位置;如果已经有键值对在这个位置了,那就调用equals方法,判断这两队键值对是否是一样的内容,若是则不存,若不是则可能以顺延的方式往后判断直到是空位置就存入的方式,也可能是其他的方式解决。希望可以帮到你!
作者: 一生1314    时间: 2015-10-29 16:36
进来看看




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2