Set之中保存的元素是不能够有重复,但是Set接口并不像List接口那样对Collection进行了方法的扩充,而是完整的继承了Collection接口的所有方法,那么也就意味着,在之前使用的get()方法无法使用了。
Set子接口之中重要使用两个常用的子类:HashSet、TreeSet。
4.1、散列存放的子类:HashSet(90%)Hash是一种散列算法,指的保存数据没有序列。
package cn.mldn.demo; import java.util.HashSet; import java.util.Set; public class TestDemo { public static void main(String[] args) throws Exception { Set all = new HashSet() ; all.add("HELLO") ; all.add("HELLO") ; // 保存了重复数据 all.add("WORLD") ; all.add("小金子") ; all.add("小谢子") ; System.out.println(all); }} |
使用HashSet是不能够保存重复数据的。而且保存的数据没有任何的顺序。
4.2、排序存放的子类:TreeSet(10%)如果希望里面的数据排序,则可以使用TreeSet子类。
package cn.mldn.demo; import java.util.Set; import java.util.TreeSet; public class TestDemo { public static void main(String[] args) throws Exception { Set all = new TreeSet() ; all.add("B") ; all.add("D") ; // 保存了重复数据 all.add("E") ; all.add("A") ; all.add("C") ; System.out.println(all); }} |
但是对于排序一般意义不大,所以使用的时候还是以HashSet为主。
4.3、关于数据排序的说明使用TreeSet可以实现集合中数据排序的保存,那么在之前使用的是String型数据,下面使用自定义类。但是这个类如果要想正常的使用TreeSet保存,那么一定要在此类上实现java.lang.Comparable接口,以区分大小。
但是在此时覆写compareTo()方法的时候必须注意到:所有的属性都必须进行比较,否则就会出现部分属性内容相同也会认为是同一对象的情况,造成数据的保存错误。
范例:使用自定义类
package cn.mldn.demo; import java.util.Set; import java.util.TreeSet; class Person implements Comparable { private String name ; private int age ; public Person(String name,int age) { this.name = name ; this.age = age ; } @Override public String toString() { return "姓名:" + this.name + ",年龄 :" + this.age + "\n" ; } @Override public int compareTo(Person o) { if (this.age > o.age) { return -1 ; } else if (this.age < o.age) { return 1 ; } return this.name.compareTo(o.name); } } public class TestDemo { public static void main(String[] args) throws Exception { Set all = new TreeSet() ; all.add(new Person("张三",20)) ; all.add(new Person("李四",21)) ; all.add(new Person("赵六",21)) ; // 年龄重复 all.add(new Person("王五",19)) ; all.add(new Person("王五",19)) ; // 彻底重复 System.out.println(all); } } |
通过此时的程序也可以得出一个结论:TreeSet使用过程之中一定要使用到Comparable接口,而且TreeSet集合里面是依靠Comparable接口的compareTo()方法返回的数据来区分是否为重复数据。
4.4、关于重复数据的说明Set子接口之中不允许保留重复数据,之前使用的TreeSet子类虽然依靠了Comparable接口进行重复数据判断,但是此判断的方式也只是针对于TreeSet这种排序结构起作用,而真正意义上的排序操作是不依靠接口的,而是依靠Object类之中的两个方法:
· 取得对象的hash码:public int hashCode();
· 对象比较:public boolean equals(Object obj);
在判断对象是否重复的过程之中,其基本流程如下:
· 首先使用要查询对象的hashCode与集合之中的保存对象的每一个hashCode进行比较;
· 如果hashCode相同,则再使用equals()方法进行内容的比较。
范例:重复对象判断
package cn.mldn.demo; import java.util.HashSet; import java.util.Set; class Person { private String name ; private int age ; public Person(String name,int age) { this.name = name ; this.age = age ; } @Override public String toString() { return "姓名:" + this.name + ",年龄 :" + this.age + "\n" ; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } } public class TestDemo { public static void main(String[] args) throws Exception { Set all = new HashSet() ; all.add(new Person("张三",20)) ; all.add(new Person("李四",21)) ; all.add(new Person("赵六",21)) ; // 年龄重复 all.add(new Person("王五",19)) ; all.add(new Person("王五",19)) ; // 彻底重复 System.out.println(all); } } |
任何情况下如果是对象的重复判断,永恒都使用hashCode()和equals()。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |