Java中hashCode和equals详解
2014-05-16 11:56
387 查看
我们先通过一个例子来看一下Set集合的运用:
从我们学习Set集合开始,老师就告诉我们,Set集合是不存在相同元素的哈,但是为什么不存在相同元素呢?比如对于上述程序很多人肯定会认为程序输出结果只有一个对象嘛,因为Set集合不能存储相同的对象啊。但是程序的输出结果是这样的:
[User [uid=1, uname=习近平], User [uid=1, uname=习近平], User [uid=1, uname=习近平]] 输出了三个对象。
其实程序输出三个对象的原因也好理解,记得上一篇文章我们提到过java的内存分配问题,new User(XXX);这样new出来的对象是存在堆区的,且他们的地址不一致,很显然他们就不是同一个对象咯。
那么是老师讲的知识点有错吗?不是的,只是我们没有搞透而已,要使得Set集合存储不同的对象,我们就必须重写父类的hashCode()和equals()方法!
我们先通过一个例子来理解一下hashCode:
程序输出结果:
从程序的运行结果我们可以看出,String和Integer等这些Java自带的类都重写了hashCode()方法,才导致了他们的hashCode值一样。但是从类A对象和类B对象的hashCode值中我们又可以发现,对于自定义的类型对象,即使对象内容一致,他们的hashCode值也不会相等,因为他们在内存中的地址不一样,就比如程序中类A的对象。但是类B就不同咯,因为我们重写了父类的hashCode()方法,所以B的对象,如果内容相同,他们的hashCode值也会相同。
总而言之:如果希望自己定义的类对象,内容一样,但由于内存空间不一样,你又想他们返回的hashCode一样,那么你就必须重写hashCode()方法!
绕了一大圈,我们还是回到最开始的那个Set集合的程序,程序中违背了我们的意愿,即我们认为的Set集合不能存储相同元素,所以现在我们要使用手段去掉Set集合中重复的元素!
1:
2:我们已经解决了第一个问题即为什么要重写hashCode()方法,现在我们来解决第二个问题,我们把这些对象都放在一个"桶"里之后,怎么去掉重复的元素呢?首先我们总要比较一下他们的内容吧!呵呵,,,方法还用我说吗?很简单,重写equals()方法即可咯,
3:以上两点我们已经闹清楚了为啥要重写hashCode()和equals()这两个方法,现在我们来讨论该如何重写hashCode()方法,equals()方法的重写在上一篇文章中详细讲解,这里就不再赘述了【如何重写这个问题,其实没必要讲,因为现在的编译器都自带有重写这两个方法的快捷键(至于怎么使用,自己百度哈)】。
重写hashCode()方法,我们的思路就是把这些内容一致的对象,让他们的hashCode值一致,比如开头的程序,我们可以这样重写:
4:这里我们在讨论一个问题:什么样的集合要重写hashCode()和equals()方法,说实话,这个自己试验一下就OK了,总结一点就是:HashTable、HashSet、HashMap这样带有Hash的集合都必须同时实现hashCode()和equals()方法,其他的集合倒是没这个要求!!!!
最后来完善一下开头的程序【这里使用编译器的快捷键来重写equals()和hashCode()方法】:
上述程序重写了equals()和hashCode()方法之后,Set集合中就没有重复的元素了,程序输出结果:
[User [uid=1, uname=习近平]] 只有一个对象,大功告成~!!!!!
class User { private Integer uid; private String uname; /* 无参构造方法 */ public User() { } /* 构造方法 */ public User(Integer uid, String uname) { this.uid = uid; this.uname = uname; } public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } @Override public String toString() { return "User [uid=" + uid + ", uname=" + uname + "]"; } } public class HashSetTest { public static void main(String[] args) { /*创建一个Set集合用于存放user*/ Collection<User> users = new HashSet<User>(); /*往集合中添加user对象*/ users.add(new User(1, "习近平")); users.add(new User(1, "习近平")); users.add(new User(1, "习近平")); /*输出集合中的元素*/ System.out.println(users); } }
从我们学习Set集合开始,老师就告诉我们,Set集合是不存在相同元素的哈,但是为什么不存在相同元素呢?比如对于上述程序很多人肯定会认为程序输出结果只有一个对象嘛,因为Set集合不能存储相同的对象啊。但是程序的输出结果是这样的:
[User [uid=1, uname=习近平], User [uid=1, uname=习近平], User [uid=1, uname=习近平]] 输出了三个对象。
其实程序输出三个对象的原因也好理解,记得上一篇文章我们提到过java的内存分配问题,new User(XXX);这样new出来的对象是存在堆区的,且他们的地址不一致,很显然他们就不是同一个对象咯。
那么是老师讲的知识点有错吗?不是的,只是我们没有搞透而已,要使得Set集合存储不同的对象,我们就必须重写父类的hashCode()和equals()方法!
我们先通过一个例子来理解一下hashCode:
class A{ private Integer id; public A(Integer id) { super(); this.id = id; } } class B{ private Integer id; public B(Integer id) { super(); this.id = id; } /*重写父类的hashCode()方法*/ public int hashCode() { return new Integer(id).hashCode(); } } public class HashCodeTest { public static void main(String[] args) { /*测试类A对象的hashCode码*/ System.out.println("new A(8).hashCode() = " + new A(8).hashCode()); System.out.println("new A(8).hashCode() = " + new A(8).hashCode()); /*测试类B对象的hashCode码*/ System.out.println("\nnew B(8).hashCode() = " + new B(8).hashCode()); System.out.println("new B(8).hashCode() = " + new B(8).hashCode()); /*测试String类对象的hashCode值*/ System.out.println("\nnew String(\"习近平\").hashCode() = " + new String("习近平").hashCode()); System.out.println("new String(\"习近平\").hashCode() = " + new String("习近平").hashCode()); /*测试字符串常量的hashCode值*/ System.out.println("\n\"习近平\".hashCode() = " + "习近平".hashCode()); System.out.println("\"习近平\".hashCode() = " + "习近平".hashCode()); /*测试Integer对象的hashCode值*/ System.out.println("\nnew Integer(8).hashCode() = " + new Integer(8).hashCode()); System.out.println("new Integer(8).hashCode() = " + new Integer(8).hashCode()); } }
程序输出结果:
从程序的运行结果我们可以看出,String和Integer等这些Java自带的类都重写了hashCode()方法,才导致了他们的hashCode值一样。但是从类A对象和类B对象的hashCode值中我们又可以发现,对于自定义的类型对象,即使对象内容一致,他们的hashCode值也不会相等,因为他们在内存中的地址不一样,就比如程序中类A的对象。但是类B就不同咯,因为我们重写了父类的hashCode()方法,所以B的对象,如果内容相同,他们的hashCode值也会相同。
总而言之:如果希望自己定义的类对象,内容一样,但由于内存空间不一样,你又想他们返回的hashCode一样,那么你就必须重写hashCode()方法!
绕了一大圈,我们还是回到最开始的那个Set集合的程序,程序中违背了我们的意愿,即我们认为的Set集合不能存储相同元素,所以现在我们要使用手段去掉Set集合中重复的元素!
1:
new User(1, "习近平"); new User(1, "习近平"); new User(1, "习近平");new出来的这三个显然是不相等的,虽然他们内容相同,但是内存地址不一样【在堆中的位置也就不一致】,所以导致了他们的hashCode值也是不一样的,我们现在的任务就是把这些不同的对象放到一个"桶"里,然后再从这个"桶"里把相同的元素去掉即可(这种解题的思路其实很简单),那么如何把这些内容一致但是内存地址不一样的对象存在一个"桶"里呢?答案我想大家已经知道了,呵呵,,,明显是要重写hashCode()方法嘛!
2:我们已经解决了第一个问题即为什么要重写hashCode()方法,现在我们来解决第二个问题,我们把这些对象都放在一个"桶"里之后,怎么去掉重复的元素呢?首先我们总要比较一下他们的内容吧!呵呵,,,方法还用我说吗?很简单,重写equals()方法即可咯,
3:以上两点我们已经闹清楚了为啥要重写hashCode()和equals()这两个方法,现在我们来讨论该如何重写hashCode()方法,equals()方法的重写在上一篇文章中详细讲解,这里就不再赘述了【如何重写这个问题,其实没必要讲,因为现在的编译器都自带有重写这两个方法的快捷键(至于怎么使用,自己百度哈)】。
重写hashCode()方法,我们的思路就是把这些内容一致的对象,让他们的hashCode值一致,比如开头的程序,我们可以这样重写:
@Override public int hashCode() { /*把所有内容以字符串的形式捆绑在一起,然后直接调用hashCode()方法即可*/ return new String(uid + uname).hashCode(); }
4:这里我们在讨论一个问题:什么样的集合要重写hashCode()和equals()方法,说实话,这个自己试验一下就OK了,总结一点就是:HashTable、HashSet、HashMap这样带有Hash的集合都必须同时实现hashCode()和equals()方法,其他的集合倒是没这个要求!!!!
最后来完善一下开头的程序【这里使用编译器的快捷键来重写equals()和hashCode()方法】:
class User { private Integer uid; private String uname; /* 无参构造方法 */ public User() { } /* 构造方法 */ public User(Integer uid, String uname) { this.uid = uid; this.uname = uname; } public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } /*重写父类的hashCode()方法*/ public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((uid == null) ? 0 : uid.hashCode()); result = prime * result + ((uname == null) ? 0 : uname.hashCode()); return result; } /*重写父类的equals()方法*/ public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; User other = (User) obj; if (uid == null) { if (other.uid != null) return false; } else if (!uid.equals(other.uid)) return false; if (uname == null) { if (other.uname != null) return false; } else if (!uname.equals(other.uname)) return false; return true; } @Override public String toString() { return "User [uid=" + uid + ", uname=" + uname + "]"; } } public class HashSetTest { public static void main(String[] args) { /*创建一个Set集合用于存放user*/ Collection<User> users = new HashSet<User>(); /*往集合中添加user对象*/ users.add(new User(1, "习近平")); users.add(new User(1, "习近平")); users.add(new User(1, "习近平")); /*输出集合中的元素*/ System.out.println(users); } }
上述程序重写了equals()和hashCode()方法之后,Set集合中就没有重复的元素了,程序输出结果:
[User [uid=1, uname=习近平]] 只有一个对象,大功告成~!!!!!
相关文章推荐
- java中hashcode()和equals()的详解
- java中的hashcode()和equals()方法详解
- java中hashcode()和equals()的详解
- java中hashcode()和equals()的详解
- Java中的hashcode()和equals()方法详解
- java中hashcode()和equals()的详解
- java中hashcode()和equals()的详解
- java中hashcode()和equals()的详解
- java中hashcode()和equals()的详解
- java中hashcode()和equals()的详解(转载)
- Java中的hashcode()和equals()方法详解
- java中hashcode()和equals()的详解
- [转]java中hashcode()和equals()的详解
- java中hashcode()与equals()详解
- java中hashcode()和equals()的详解
- java中hashcode()和equals()的详解
- java中hashcode()和equals()的详解
- java中hashcode()和equals()的详解[转]
- java中hashcode()和equals()的详解
- java中hashcode()和equals()的详解