HashSet原理
来源:互联网 发布:linux虚拟机和双系统 编辑:程序博客网 时间:2024/05/21 09:02
1. HashSet
1). HashSet验证Set的无序性和唯一性
(1). HashSet验证无序性
示例代码:
- //1. 验证无序性
- class HashDemoI
- {
- public static void sop(Object o){
- System.out.println(o);
- }
- public static void main(String[] args){
- HashSeths =new HashSet();
- hs.add("java001");
- hs.add("java002");
- hs.add("java003");
- hs.add("java004");
- Iteratorit =hs.iterator();
- while(it.hasNext()){
- sop(it.next());
- }
- }
- }
打印结果:
java04
java02
java03
java01
【结论】存入的时候,是java01~java04 取出的时候是java04、java02、java03、java01 存入时候的顺序和存储、取出的顺序不一致,所以通过HashSet可以检验Set是无序的。
(2). HashSet验证唯一性
[1]. 存入的对象是字符串 ----并重复传入一个字符串对象
- //2. 验证唯一性
- public class HashSetDemoII {
- public static void sop(Object o){
- System.out.println(o);
- }
- public static void main(String[] args){
- HashSeths =new HashSet();
- sop("java001 really add? "+ hs.add("java001"));
- sop("java001 really add? "+ hs.add("java001"));
- sop("java002 really add? "+ hs.add("java002"));
- sop("java003 really add? "+ hs.add("java003"));
- sop("java003 really add? "+ hs.add("java003"));
- sop("最终元素集合中的内容...");
- Iteratorit =hs.iterator();
- while(it.hasNext()){
- sop(it.next());
- }
- }
- }
打印结果:
【结论】为什么Collection的add方法返回值是boolean类型的?
这个boolean类型表示向集合中添加元素是否成功。不成功,add返回false;否则,返回true
【分析】运行完sop("java001 really add? "+ hs.add("java001"));之后,接着运行 sop("java001 really add? "+ hs.add("java001"));,向hs集合中添加相同的元素。此时hs的底层数据结构调用了String类的equals方法。由于String类的equals方法重写过,判定结果是这两个对象的内容一样,所以,没有将第二个"java001"添加到集合中。此时add方法返回false。
[2]. 存入的对象是自定义对象
{1}. 测试代码不变:
- class HashSetDemoIII
- {
- public static void sop(Object o){
- System.out.println(o);
- }
- public static void main(String[] args){
- HashSeths =new HashSet();
- hs.add(new Person("a1", 11));
- hs.add(new Person("a2", 12));
- hs.add(new Person("a3", 13));
- hs.add(new Person("a2", 12));
- Iteratorit =hs.iterator();
- while(it.hasNext()){
- sop(it.next());
- }
- }
- }
{2}. 没有重写equals
示例代码
- //2. 验证唯一性,存入自定义元素
- class Person{
- private String name;
- private int age;
- public static void sop(Object o){
- System.out.println(o);
- }
- public Person(String name, int age){
- this.name =name;
- this.age =age;
- }
- public void setName(String name){
- this.name =name;
- }
- public String getName(){
- return this.name;
- }
- public void setAge(int age){
- this.age =age;
- }
- public int getAge(){
- return this.age;
- }
- public String toString(){
- return this.name+"::"+this.age;
- }
- }
测试结果:
【结论】循环迭代结果:a2::12被打印了两次,说明重复的元素new Person("a2", 12)被添加到集合中去。没有保证HashSet的唯一性。
{3}. 为Person类重写equals()方法判定两个对象的内容是否一致
- public boolean equals(Object obj){
- if(!(obj instanceof Person)){
- return false;
- }
- Personp =(Person)obj;
- //用来查看equals方法是否被调用
- sop(this.name +".......equals......."+ p.name);
- //认为名字相同并且年龄一样大的两个对象是一个
- return this.name.equals(p.name) && this.age == p.age;
- }
测试结果:
【结论】循环迭代结果:a2::12被打印了两次,说明重复的元素new Person("a2", 12)被添加到集合中去。没有保证HashSet的唯一性。
同时equals没有被调用,说明仅仅重写equals方法没起到作用
【分析】HashSet在存储元素的时候,是先查看两个对象的哈希值是否一样的。
{3}【1】.
如果哈希值是一样,再调用元素对象的equals方法,查看两个对象的内容是否一样。
{1}. 如果equlas比较的值一样,说明两个对象相同,不能添加到HashSet对应的集合中。
{2}. 如果equlas比较的值不一样,说明两个对象不同,可以添加到HashSet对应的集合中
{3}【2】.
如果哈希值是不一样,直接认为两个对象不一样,equals方法不起作用。
【本例分析】这个例子中,由于四个Person类的对象都是new出来的,所以没有重写的hashCode是调用本地方法产生的值,所以一定是四个不相同的hashCode值。hashCode值都不一样,equals方法不起作用。
(3). 重写HashCode方法
为避免内容重复的数据添加到HashSet集合中,就必须重写hashCode()方法。
[1]. hashCode的返回值设置为统一的数值:
示例代码:
- public int hashCode(){
- System.out.println(this.name +"...hashCode");
- return 60;
- }
打印结果:
重复的元素没有被添加进来。
【建议】不要将hashCode的返回值都设置成一样的。因为hashCode的值和内存地址有关,这样设置不科学
[2]. 根据比较的条件重写HashCode方法
- public int hashCode(){
- sop(this.name +"......hashCode");
- return this.name.hashCode() + 29*age;
- }
这种做法,同样可以避免HashSet集合中不会存入相同元素。
【两种方式的具体区别和详细过程见个人总结。】
(4). 重写hashCode和equals的时候,常犯的错误
[1]. 子类重写hashCode的时候,将方法名写错,写成hasCode
[2]. 子类重写equals的时候,将参数传错,本来应该是public boolean equals(Object obj){}却写成了public boolean equals(自定义类型自定义类型引用)。这样集合框架的底层不会调用这个重载的方法。
2. HashSet总结
1). HashCode如何保证元素唯一性?
(1). 需要重写的方法
通过重写自定义类的hashCode()和equals( )两个方法来达到元素的唯一性保证。
(2). 方法重写之后,执行的顺序
[1]. 如果元素的hashCode值相同,才会使用equals()方法进行判断。
[2]. 如果元素的hashCode值不同,不会调用equals()方法。
2). 开发中的建议
(1). 自定义对象,一定要重写hashCode和equals两个方法
如果不重写,则默认的本地方法hashCode【OS来产生】会产生值都不一样的hashCode,即使内容重复的元素也会被添加到HashSet中,无法保证元素的唯一性。
【注意】开发中重写这两个方法,方便集合框架的底层调用这些方法。
(2). 建立高效的hashCode会使得hashSet添加元素的过程更为高效。
hashCode的值不同,则调用equals()方法比较的环节便可以省去。
3). HashSet判断和删除元素的依据
示例代码:
- public class HashSetDemoIV {
- public static void main(String[] args) {
- HashSeths =new HashSet();
- hs.add(new Person("a1", 11));
- hs.add(new Person("a2", 12));
- hs.add(new Person("a3", 13));
- System.out.println("hashSet中的元素:"+ hs);
- System.out.println("************************");
- System.out.println("HashSet的 contains依据:"+ hs.contains(new Person("a1", 11)));
- System.out.println("************************");
- System.out.println("HashSet的 remove依据:"+ hs.remove(new Person("a3", 13)));
- System.out.println("************************");
- System.out.println("hashSet中的元素:"+ hs);
- }
- }
打印结果:
可以看出,hashSet在删除和判断元素的时候,依据的仍然是hashCode和equals这两个方法。
结论:
[1]. HashSet判断、删除和添加元素等操作依据的是被操作元素所在的类的hashCode()和equals( )这两个方法。
[2]. ArrayList做同等的操作,依据的仅仅是equals( )方法
- HASHSET原理
- HashSet原理
- hashSet 原理
- hashset原理
- HashSet的实现原理
- HashSet的实现原理
- HashSet/HashTree工作原理
- HashSet的实现原理
- HashSet的存储原理
- HashSet的实现原理
- HashSet的实现原理
- 一个HashSet原理问题
- HashSet的实现原理
- Hashset实现原理
- JAVA HashSet 原理分析
- HashSet的实现原理
- java hashset 原理
- HashSet实现原理
- ModelAndView详解
- poj 2178 Beauty Contest[最远点对]
- measureChildren的工作原理
- [mysql]mac在命令行使用mysql
- Ubuntu 14.04输入法安装
- HashSet原理
- 最小生成树-kruskal模板
- sql中通配符
- IntentService多线程
- LA4329
- java 操作excel,jxl加边框,jxl合并单元格,单元格的设置,单元
- UVA - 639 Don't Get Rooked (回溯)
- JavaScript 基础
- 【最短路径】poj 1062