首页 > 代码库 > Java学习笔记_22_Set接口的实现类
Java学习笔记_22_Set接口的实现类
22.Set接口的实现类:
Set接口存放的元素是无序的且不包含重复元素。
1>实现类HashSet:
HashSet类根据元素的哈希码进行存放,取出时也可以根据哈希码快速找到。HashSet不保存元素的添加的顺序。
例子:
import java.util.HashSet; import java.util.Iterator; public class Student { public static void main(String[] args) { HashSet<String> hs = new HashSet<String>(); hs.add("1 zxx"); hs.add("1 zxx"); hs.add("2 hahx"); hs.add("3 zyj"); hs.add("4 bmh"); Iterator<String> it = hs.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }
输出结果:
1 zxx
4 bmh
3 zyj
2 hahx
因为Set集合中不能存放重复的元素,所以对于自定义的类,要重写hashCode()和equals()方法,用来判断元素是否为重复对象。
例子:
public class Student { private int age; private String name; // get、set方法省略 public Student(int age, String name) { this.age = age; this.name = name; } // 重写HashCode方法 public int hashCode() { return age * name.hashCode(); } // 重写equals方法 public boolean equals(Object obj) { Student s = (Student) obj; return age == s.age && name.equals(s.name); } }
注:如果两个对象相同,那么它们的hashCode值一定要相同;如果两个对象的hashCode值相同,他们并不一定相同。
2>实现类LinkedHashSet:
LinkHashSet类根据元素的哈希码进行存放,同时用链表记录元素的加入顺序。
简单的字符集合例子:
import java.util.Iterator; import java.util.LinkedHashSet; public class TestLinkedHashSet { public static void main(String[] args) { //创建一个LinkedHashSet集合对象 LinkedHashSet<String> lhs = new LinkedHashSet<String>(); //向集合对象中添加字符串 lhs.add("zxx"); lhs.add("abc"); lhs.add("hik"); lhs.add("hik"); lhs.add(null); //生成一个迭代器 Iterator<String> it = lhs.iterator(); //输出字符串 while(it.hasNext()){ System.out.println(it.next()); } } }
输出为:
zxx
abc
hik
Null
自定义对象的集合使用例子:
创建Student类:
public class Student { //创建属性 private int age; private String name; //生成属性的get和set方法 public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } //包含参数的构造函数 public Student(int age, String name) { this.age = age; this.name = name; } //重写toString方法 public String toString() { return "age :" + age + " name :" + name; } // 重写HashCode方法 public int hashCode() { return age * name.hashCode(); } // 重写equals方法 public boolean equals(Object obj) { Student s = (Student) obj; return age == s.age && name.equals(s.name); } }
测试LinkedHashSet的主函数:
import java.util.Iterator; import java.util.LinkedHashSet; public class TestLinkedHashSet { public static void main(String[] args) { //创建一个LinkedHashSet集合对象 LinkedHashSet<Student> lhs = new LinkedHashSet<Student>(); //生成一些Student对象 Student sd1 = new Student(18, "zxx"); Student sd2 = new Student(23, "abc"); Student sd3 = new Student(25, "hik"); Student sd4 = new Student(25, "hik"); //向集合对象中添加Student对象 lhs.add(sd4); lhs.add(sd2); lhs.add(sd3); lhs.add(sd1); lhs.add(null); //生成一个迭代器 Iterator<Student> it = lhs.iterator(); //输出字符串 while (it.hasNext()) { System.out.println(it.next()); } } }
输出:
age :25 name :hik
age :23 name :abc
age :18 name :zxx
null
注:通过链表来存储对象,一般插入和删除效率比较高,检索效率相对较低。
3>实现类TreeSet:
TreeSet的构造方法:
· TreeSet(): 构造一个空树集。
· TreeSet(Collection c): 构造一个树集,并添加集合c中的所有元素。
· TreeSet(Comparator c): 构造一个树集,并且使用特定的比较器对其经行排序。
· TreeSet(SortedSet s): 构造一个树集,添加有序集合s中的所有元素,并且使用与有序集s相同的比较器排序。
注意:放入TreeSet中的元素必须是可以排序的。假若要对加入的Student类经行排序,
则要实现compareTo()方法,那么就必须实现Comparable接口。
排序Student集合类例子:
Student中的代码:
public class Student implements Comparable { // 创建属性 private Integer age; private String name; // 包含参数的构造函数 public Student(Integer age, String name) { this.age = age; this.name = name; } // 生成属性的get和set方法 public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 重写toString方法 public String toString() { return "age :" + age + " name :" + name; } // 重写HashCode方法 public int hashCode() { return age * name.hashCode(); } // 重写equals方法 public boolean equals(Object obj) { Student s = (Student) obj; return age == s.age && name.equals(s.name); } //重写compareTo(Object o)方法 public int compareTo(Object o) { Student s = (Student) o; if (s.getAge().compareTo(this.getAge()) > 0) return -1; else if (s.getAge().compareTo(this.age) == 0) return 0; else return 1; } }
TestTreeSet类中的代码:
import java.util.Iterator; import java.util.Set; import java.util.TreeSet; public class TestTreeSet { public static void main(String[] args) { // 创建一个LinkedHashSet集合对象 Set<Student> ts = new TreeSet<Student>(); // 生成一些Student对象 Student sd1 = new Student(18, "zxx"); Student sd2 = new Student(23, "abc"); Student sd3 = new Student(25, "hik"); Student sd4 = new Student(25, "hik"); Student sd5 = new Student(17, "cde"); // 向集合对象中添加Student对象 lhs.add(sd4); ts.add(sd2); ts.add(sd5); ts.add(sd3); ts.add(sd1); // 生成一个迭代器 Iterator<Student> it = ts.iterator(); // 输出字符串 while (it.hasNext()) { System.out.println(it.next()); } } }
输出结果:
age :17 name :cde
age :18 name :zxx
age :23 name :abc
age :25 name :hik
很明显TreeSet中的Student类按age由小到大的顺序排序。
使用Comparable接口可以完成TreeSet的排序,但使用Comparable接口定义排序具有局限性,
实现此接口的类只能按CompareTo()定义的这一种方法排序。如果同一类对象要有多种排序方式,
应该为该类定义不同的比较器。定义比较器实际上就是让自编写的类实现Comparator接口,
重写Comparator接口中的比较方法compare(Object a,Object b)。
排序Student集合类例子:
Student中的代码:
public class Student { // 创建属性 private Integer age; private String name; private Integer score; // 包含参数的构造函数 public Student(Integer age, String name, Integer score) { this.age = age; this.name = name; this.score = score; } // 重写toString方法 public String toString() { return "name :" + name + " age :" + age + " score :" + score; } // 生成属性的get和set方法 public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getScore() { return score; } public void setScore(Integer score) { this.score = score; } // 重写HashCode方法 public int hashCode() { return age * score * name.hashCode(); } // 重写equals方法 public boolean equals(Object obj) { Student s = (Student) obj; return age == s.age && name.equals(s.name) && score == s.score; } }
TestTreeSet类中的代码:
import java.util.Comparator; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; //学生年龄比较器 class StudentAgeComparator implements Comparator<Student> { public int compare(Student o1, Student o2) { int i = o1.getAge() - o2.getAge(); return i; } } // 学生成绩比较器 class StudentScoreComparator implements Comparator<Student> { public int compare(Student o1, Student o2) { int i = o1.getScore() - o2.getScore(); return i; } } public class TestTreeSet { public static void main(String[] args) { // 创建一个LinkedHashSet集合对象 //按年龄有小到大排顺序 Set<Student> ts = new TreeSet<Student>(new StudentAgeComparator()); //按成绩由小到大排序 //Set<Student> ts = new TreeSet<Student>(new StudentScoreComparator()); // 生成一些Student对象 Student sd1 = new Student(18, "zxx", 60); Student sd2 = new Student(23, "abc", 85); Student sd3 = new Student(25, "hik", 45); Student sd4 = new Student(25, "hik", 90); Student sd5 = new Student(17, "cde", 33); // 向集合对象中添加Student对象 ts.add(sd1); ts.add(sd2); ts.add(sd3); ts.add(sd4); ts.add(sd5); // 生成一个迭代器 Iterator<Student> it = ts.iterator(); // 输出字符串 while (it.hasNext()) { System.out.println(it.next()); } } }
当选用Set<Student> ts = new TreeSet<Student>(new StudentAgeComparator());时。
输出结果:
name :cde age :17 score :33
name :zxx age :18 score :60
name :abc age :23 score :85
name :hik age :25 score :45
很明显是按年龄由小到大排序的。
当选用Set<Student> ts = new TreeSet<Student>(new StudentScoreComparator());时。
输出结果:
name :cde age :17 score :33
name :hik age :25 score :45
name :zxx age :18 score :60
name :abc age :23 score :85
name :hik age :25 score :90
很明显是按成绩由小到大排序的。