--------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流! --------------------
1.Set
Set是Collection接口的子接口,此集合中不能存放重复元素,对于比较方式是根据他们的底层结构决定的,常见的子类有:HashSet和TreeSet
2.HashSet
1. 概述
底层是哈希表:哈希值是Object类中哈希方法返回的值,读取此集合中的元素是必须使用迭代器,比较的时候,先是比较的哈希值,如果哈希值相同那么就比较equals方法。
2. 无序性
package www.fuxi.jihe; import java.util.HashSet; import java.util.Iterator; public class HashSetDemo { public static void main(String[]args) { HashSet set = new HashSet();// HashSet对象 set.add("java01"); set.add("java02");// 添加元素 set.add("java03"); Iterator it = set.iterator();// 迭代器读取数据 while (it.hasNext()) { System.out.println(it.next()); } } } 结果: java02 java03 java01
从结果可以看出,他们的读取出来的顺序和存入的顺序是不同的,所以说明他们元素是无序的。
3. 不可重复性
package www.fuxi.jihe; import java.util.HashSet; import java.util.Iterator; public class HashSetDemo { public static void main(String[] args) { HashSet set = new HashSet();// HashSet对象 set.add("java01"); set.add("java02");// 添加元素 set.add("java03"); System.out.println("java02是否存储集合中:"+set.add("java02")); Iterator it = set.iterator();// 迭代器读取数据 while (it.hasNext()) { System.out.println(it.next()); } } } 结果: java02是否存储集合中:false java02 java03 java01 从结果可以看出他们java02没有存储里面,所以,集合中不能存储相同的元素
4.比较的原理
他们首先比较的哈希值,如果哈希值相同,那么他们就开始比较他们的equals方法,同时也可以自定义比较规则,就是重写HashCode()和equals()方法。
重写的时候一定要和Object类中定义的一样,equals的参数是Object类型,public boolean equals(Object ob){},public int hashCode();
在这里也说一下ArrayList和LinkedList集合,他们的比较方式,他们就是基于equals方法
package www.fuxi.jihe; public class Person { private String name;// 姓名 private int age;// 年龄 public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } /* * 这个重写hashCode()方法,在这里返回的哈希值是一样的,为了测试是不是调用的此方法,若哈希值相同,调用的是否是equals()方法 */ public int hashCode() { System.out.println(this.getName() + "--hashCode()"); return 20; } /* equals()方法重写 */ public boolean equals(Object ob) { if (!(ob instanceof Person)) { return false; } Person p = (Person) ob; System.out.println(this.getName() + "--equals---" + p.getName()); return this.name.equals(p.name) && this.age == p.age; } } package www.fuxi.jihe; import java.util.HashSet; import java.util.Iterator; public class HashSetDemo { publicstatic void main(String[] args) { HashSetset = new HashSet();// HashSet对象 set.add(newPerson("zhangsan",21)); set.add(newPerson("lisi",22));// 添加元素 set.add(newPerson("zhangsan",21)); System.out.println("读取集合中的元素:"); Iteratorit = set.iterator();// 迭代器读取数据 while(it.hasNext()) { Personob=(Person)it.next(); System.out.println(ob.getName()+":"+ob.getAge()); } } } 结果: zhangsan--hashCode() lisi--hashCode() lisi--equals---zhangsan zhangsan--hashCode() zhangsan--equals---lisi zhangsan--equals---zhangsan 读取集合中的元素: lisi:22 zhangsan:21
从结果中可以看出,每次存储对象后,都会调用hashCode()方法,在这个哈希值都一样,所以她们都会再次调用equals方法,
但是如果你没有重写hashCode()方法,那么每次添加新的对象若都使用了new创建的对象,那么他们的hashCode()的是不一样,所以我们可以自定义hashCode和equals方法
如果我们hashCode()方法重写的恰到好处的话,那么equals方法减少了比较次数。
package www.fuxi.jihe; public class Person { private String name;// 姓名 private int age;// 年龄 public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } /* * 重写hashCode()方法,这样的哈希值差不多都很难不一样的 */ public int hashCode() { return this.name.hashCode()+this.age*56; } /* equals()方法重写 */ public boolean equals(Object ob) { if (!(ob instanceof Person)) { return false; } Person p = (Person) ob; System.out.println(this.getName() + "--equals---" + p.getName()); return this.name.equals(p.name) && this.age == p.age; } }
在这里说一下,对于集合存储的自定义对象,那么使用读取出来的是Object类型,所以我们要是使用对象的方法,那么我需要把其强制类型转换为我们需要的类型。
3. HashSet的删除和判断
package www.fuxi.jihe; public class Person { private String name;// 姓名 private int age;// 年龄 public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } /* * 重写hashCode()方法,这样的哈希值差不多都很难不一样的 */ public int hashCode() { int code = this.name.hashCode() + this.age * 56; System.out.println(this.name + ":"+this.age+"---Code=" + code); return code; } /* equals()方法重写 */ public boolean equals(Object ob) { if (!(ob instanceof Person)) { return false; } Person p = (Person) ob; System.out.println(this.getName() + "--equals---" + p.getName()); return this.name.equals(p.name) && this.age == p.age; } } packagewww.fuxi.jihe; importjava.util.HashSet; importjava.util.Iterator; public classHashSetDemo { public static void main(String[] args) { HashSet set = new HashSet();//HashSet对象 set.add(newPerson("zhangsan",21)); set.add(newPerson("lisi",22));// 添加元素 set.add(newPerson("zhangsan",21)); System.out.println("是否存此对象:"+set.contains(new Person("lisi",22))); System.out.println("是否存此对象:"+set.contains(newPerson("wangwu",20))); System.out.println("移除此对象:"+set.remove(newPerson("zhangsan",21))); } } 结果: zhangsan:21---Code=-1432603380 lisi:22---Code=3323235 zhangsan:21---Code=-1432603380 zhangsan--equals---zhangsan lisi:22---Code=3323235 lisi--equals---lisi 是否存此对象:true wangwu:20---Code=-795135871 是否存此对象:false zhangsan:21---Code=-1432603380 zhangsan--equals---zhangsan 移除此对象:true
从结果中可以看出也是在判断的时候也是依赖于hashCode()和equals()方法,在这里hashCode()方法设置的比较巧妙,哈希值都不一样,所以没有机会执行equals方法
--------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!
--------------------