深入详解SetHash的元素为什么要重写hashCode和equals方法
2017-06-15 17:26
627 查看
在Object这个类中hashCode是本地方法,它的值与对象在内存中的地址有关,所以不会存在两个hashCode返回值相同的对象,equals是比较对象的引用是否相等
hashCode方法的目的是什么呢?
—它是为hash table中插入为提供hash数值
SetHash:一个是无序不重复的集合,你知道为什么吗?
因为SetHash根据hashCode返回值和equals来判断两个对象是否相同(不止地址还指内容)
在HashCode的返回值判断插入位置,equals判断该位置上是否有和要插入的元素相同的
所以要保证SetHash插入的元素不重复,那就要重写hashCode和equals
我们先举一个没有重写hashCode和equals的例子吧
先定义一个元素类Point
再定一个Test类
按理论上讲应该输出:
(4,5),(1,5)这两个值,因为有重复的(4,5)
但是实际输出却是这样
为什么呢?因为没有重写hashCode导致两个(4,5)的插入位置不一样或者插入一样但是,两个对象的引用地址不一样
重写equals的目的是:让两个(4,5)引用地址不一样,但内容一样的对象是相等的
重写hashCode的目的:让A.equals(B)为true的两个对象的hashCode返回值一样
在这里有可能有小伙伴有疑问?问可不可以不重写hashCode呢?
答案是不可以,为什么?让我们有例子来解答疑惑
还是刚才个例子,我们重写了equals方法
测试类
你们猜结果为什么?应该是true吧
但是输出却为false,为什么呢?
因为p和p1的hashCode不一样就用可能不会插入到同一个位置,所以会返回false
因此使用HashSet 的add()方法插入元素的时候:
|- HashSet会自动调用元素的hashCode()方法。
|- 然后根据hashCode()方法的返回值 来决定元素要插入的位置。
|- 如果该位置上已经存在元素了 则会调用该元素equals()方法进行比较。
|- 如果两个元素相等 则丢掉欲插入的元素。
|- 如果两个元素不相等 则新元素会被加入到另一个位置(通过冲突检测来决定哪一个位置),这样就消除了重复。
|- 范例1中使用的是Point类 其并没有重写这2个方法。因此无法消除重复。
|- 范例2中使用的是String类,在String类已经重写完了Object类的equals()和hashCode()方法,所以可以消除重复。
说白了:
|- 如果想完整的使用HashSet类 那么最少要重写equals()和hashCode()方法。
|- 重写hashCode() 用于获得元素的存储位置。
|- 重写equals() 用于在两个元素的位置相同的时候 比较两个元素是否相等。
总结一下:
Set接口有两个子类:HashSet和TreeSet 。
|- HashSet
|- 特点:在不存在重复元素的基础上,还可以进行高速的存取元素。
|- 要求:需要为您的类重写hashCode()和equals()方法。
|- TreeSet
|- 特点:在不存在重复元素的基础上,还可以将元素自动排序。
|- 要求:需要为您的类实现Comparable接口,并重写compareTo方法。
|- 重写compareTo() 可以同时完成两份工作 排序和消除重复。
能帮到你们,我十分荣幸
hashCode方法的目的是什么呢?
—它是为hash table中插入为提供hash数值
SetHash:一个是无序不重复的集合,你知道为什么吗?
因为SetHash根据hashCode返回值和equals来判断两个对象是否相同(不止地址还指内容)
在HashCode的返回值判断插入位置,equals判断该位置上是否有和要插入的元素相同的
所以要保证SetHash插入的元素不重复,那就要重写hashCode和equals
我们先举一个没有重写hashCode和equals的例子吧
先定义一个元素类Point
class Point{ private int a; private int b; public Point(int a,int b){ this.a = a; this.b = b; } @Override public String toString(){ return "("+a+","+b+")"; }
再定一个Test类
public class TestHashSet { public static void main(String[] args) { // TODO Auto-generated method stub HashSet<Point> hash = new HashSet<Point>(); hash.add(new Point(4,5)); hash.add(new Point(4,5)); hash.add(new Point(1,5)); for(Point p:hash){ System.out.println(p); } } }
按理论上讲应该输出:
(4,5),(1,5)这两个值,因为有重复的(4,5)
但是实际输出却是这样
为什么呢?因为没有重写hashCode导致两个(4,5)的插入位置不一样或者插入一样但是,两个对象的引用地址不一样
重写equals的目的是:让两个(4,5)引用地址不一样,但内容一样的对象是相等的
重写hashCode的目的:让A.equals(B)为true的两个对象的hashCode返回值一样
在这里有可能有小伙伴有疑问?问可不可以不重写hashCode呢?
答案是不可以,为什么?让我们有例子来解答疑惑
还是刚才个例子,我们重写了equals方法
class Point{ private int a; private int b; public Point(int a,int b){ this.a = a; this.b = b; } @Override public String toString(){ return "("+a+","+b+")"; }
***@Override
public boolean equals(Object obj){
if(this==obj)
return true;
if(!(obj instanceof Point))
return false;
Point p = (Point)obj;
return this.a == p.a && this.b == p.b;
}***
}
测试类
import java.util.HashSet; public class TestSet { public static void main(String[] args) { // TODO Auto-generated method stub HashSet<Point> hash = new HashSet<Point>(); Point p = new Point(4,5); Point p1 = new Point(4,5); hash.add(p); System.out.println(hash.contains(p1)); } }
你们猜结果为什么?应该是true吧
但是输出却为false,为什么呢?
因为p和p1的hashCode不一样就用可能不会插入到同一个位置,所以会返回false
因此使用HashSet 的add()方法插入元素的时候:
|- HashSet会自动调用元素的hashCode()方法。
|- 然后根据hashCode()方法的返回值 来决定元素要插入的位置。
|- 如果该位置上已经存在元素了 则会调用该元素equals()方法进行比较。
|- 如果两个元素相等 则丢掉欲插入的元素。
|- 如果两个元素不相等 则新元素会被加入到另一个位置(通过冲突检测来决定哪一个位置),这样就消除了重复。
|- 范例1中使用的是Point类 其并没有重写这2个方法。因此无法消除重复。
|- 范例2中使用的是String类,在String类已经重写完了Object类的equals()和hashCode()方法,所以可以消除重复。
说白了:
|- 如果想完整的使用HashSet类 那么最少要重写equals()和hashCode()方法。
|- 重写hashCode() 用于获得元素的存储位置。
|- 重写equals() 用于在两个元素的位置相同的时候 比较两个元素是否相等。
总结一下:
Set接口有两个子类:HashSet和TreeSet 。
|- HashSet
|- 特点:在不存在重复元素的基础上,还可以进行高速的存取元素。
|- 要求:需要为您的类重写hashCode()和equals()方法。
|- TreeSet
|- 特点:在不存在重复元素的基础上,还可以将元素自动排序。
|- 要求:需要为您的类实现Comparable接口,并重写compareTo方法。
|- 重写compareTo() 可以同时完成两份工作 排序和消除重复。
能帮到你们,我十分荣幸
相关文章推荐
- list\set等容器(集合)那里重写equals为什么还要重写hashCode方法
- Set是如何实现元素不重复的&重写equals()方法之后也必须重写hashCode()方法
- JAVA中重写equals()方法为什么要重写hashcode()方法?
- hibernate中的po类为什么要重写equals和hashcode方法的对话
- 【Java基础】JAVA中重写equals()方法为什么要重写hashcode()方法?
- HashCode的作用 以及重写equals方法为什么要重写HashCode方法?
- HashSet的hashCode方法和equals方法的重写,TreeSet中compareTo方法的重写,Comparator在treeSet中的应用。
- JAVA中重写equals()方法为什么要重写hashcode()方法?
- ID的生成策略(hibernate的id生成策略,主键类为什么需要实现序列化接口,同时还要重写hashCode()和equals()方法)
- JAVA中重写equals()方法为什么要重写hashcode()方法?
- Java重写equals方法时为什么要重写hashcode方法
- JAVA中重写equals()方法为什么要重写hashcode()方法?
- Hibernate为什么要重写equals和hashCode方法
- 在Boss 里已重写hascode和equals 方法,且b1、b2相同,为啥set还是添加相同元素????
- JAVA中重写equals()方法为什么要重写hashcode()方法说明
- 重写equals方法的同时为什么要重写hashcode方法
- 为什么重写equals方法,一定要重写HashCode方法?
- 为什么要重写equals和hashCode方法
- 为什么重写equals方法,一定要重写HashCode方法?(
- 为什么重写equals方法,一定要重写HashCode方法?