3.2 Set接口

  Set接口是Collection接口的子接口,除了拥有Collection接口的方法外,Set接口没有提供额外的方法。

3.2.1 Set接口方法

  下面列出了Set接口继承自Collection接口的主要方法。

  • boolean add(Object obj)

  向集合中添加一个数据元素,该数据元素不能和集合中现有数据元素重复。

  Set集合采用对象的equals()方法比较两个对象是否相等,判断某个对象是否已经存在于集合中。当向集合中添加一个对象时,HashSet会调用对象的hashCode()方法来获得哈希码,然后根据这个哈希码进一步计算出对象在集合中的存放位置。

  • void clear()

  移除此集合中的所有数据元素,即将集合清空。

  • boolean contains(Object obj)

  判断此集合中是否包含该数据元素,如果包含,则返回true。

  • boolean isEmpty()

  判断集合是否为空,为空则返回true。

  • Iterator iterator()

  返回一个Iterator对象,可用它来遍历集合中的数据元素。

  • boolean remove(Object obj)

  如果此集合中包含该数据元素,则将其删除,并返回true。

  • int size()

  返回集合中数据元素的个数,注意与数组、字符串获取长度的方法的区别。

  • Object[] toArray()

  返回一个数组,该数组包含集合中的所有数据元素。

3.2.2 HashSet使用

  Set接口主要有两个实现类HashSet和TreeSet,HashSet类有一个子类LinkedHashSet,它不仅实现了哈希算法,而且采用了链表结构。接下来通过一个案例来说明HashSet类的使用。

  1. import java.util.*; //导入包
  2. public class TestSet
  3. {
  4. public static void main(String[] args)
  5. {
  6. //创建一个HashSet对象,存放学生姓名信息
  7. Set nameSet = new HashSet();
  8. nameSet.add("王云");
  9. nameSet.add("刘静涛");
  10. nameSet.add("南天华");
  11. nameSet.add("雷静");
  12. nameSet.add("王云"); //增加已有的数据元素
  13. System.out.println("再次添加王云是否成功:" + nameSet.add("王云"));
  14. System.out.println("显示集合内容:" + nameSet);
  15. System.out.println("集合里是否包含南天华:" + nameSet.contains("南天华"));
  16. System.out.println("从集合中删除\"南天华\"...");
  17. nameSet.remove("南天华");
  18. System.out.println("集合里是否包含南天华:" + nameSet.contains("南天华"));
  19. System.out.println("集合中的元素个数为:" + nameSet.size());
  20. }
  21. }

  编译、运行程序,程序运行结果如图3.3所示。从运行结果中可以看出,当向集合中增加一个已有(通过equals()方法判断)的数据元素时,没有添加成功。需要注意的是,可以通过add()方法的返回值判断是否添加成功,如果不获取这个返回值的话,Java系统并不提示没有添加成功。

3.2 Set接口 - 图1


图3.3 HashSet的使用

3.2.3 TreeSet使用

  TreeSet类在实现了Set接口的同时,也实现了SortedSet接口,是一个具有排序功能Set接口类。本小节将介绍TreeSet类的使用,同时也会涉及Java如何实现对象间的排序功能,希望大家能深刻体会。

  TreeSet集合中的元素按照升序排列,默认是按照自然升序排列,也就是说TreeSet集合中的对象需要实现Comparable接口。

  接下来看一段非常简单的程序,编译运行,其运行结果如图3.4所示。

  1. import java.util.*;
  2. public class TestTreeSet
  3. {
  4. public static void main(String[] args)
  5. {
  6. Set ts = new TreeSet();
  7. ts.add("王云");
  8. ts.add("刘静涛");
  9. ts.add("南天华");
  10. System.out.println(ts);
  11. }
  12. }

3.2 Set接口 - 图2


图3.4 TreeSet的使用

  从运行结果可以看出,TreeSet集合ts里面的元素不是毫无规律的排序,而是按照自然升序进行了排序。这是因为TreeSet集合中的元素是String类,而String类实现了Comparable接口,默认按自然顺序排序。

3.2.4 Comparable接口

  如果程序员想定义自己的排序方式,方法也很简单,就是要让加入TreeSet集合中的对象所属的类实现Comparable接口,通过实现compareTo(Object o)方法,达到排序的目的。

  假设有这样的需求,学生对象有两个属性,分别是学号和姓名。希望将这些学生对象加入TreeSet集合后,按照学号大小从小到大进行排序,学号相同的再按照姓名自然排序。让我们来看学生类的代码(实现Comparable接口):

  1. class Student implements Comparable {
  2. int stuNum = -1; //学生学号
  3. String stuName = ""; //学生姓名
  4. Student(String name, int num) {
  5. this.stuNum = num;
  6. this.stuName = name;
  7. }
  8. //返回该对象的字符串表示,利于输出
  9. public String toString() {
  10. return "学号为:" + stuNum + "的学生,姓名为:" + stuName;
  11. }
  12. //实现Comparable的compareTo方法
  13. public int compareTo(Object o) {
  14. Student input = (Student) o;
  15. //此学生对象的学号和指定学生对象的学号比较
  16. //此学生对象学号若大则res为1,若小则res为-1,相同的话res = 0
  17. int res = stuNum > input.stuNum ? 1 : (stuNum == input.stuNum ? 0 : -1);
  18. //若学号相同,则按照String类自然排序比较学生姓名
  19. if (res == 0) {
  20. res = stuName.compareTo(input.stuName);
  21. }
  22. return res;
  23. }
  24. }

  其中,int compareTo(Object o)方法是用此对象和指定对象进行比较,如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。编写测试程序,具体代码如下。程序运行结果如图3.5所示。

  1. public class TestTreeSet2{
  2. public static void main(String[] args) {
  3. //用有序的TreeSet存储学生对象
  4. Set stuTS = new TreeSet();
  5. stuTS.add(new Student("王云",1));
  6. stuTS.add(new Student("南天华",3));
  7. stuTS.add(new Student("刘静涛",2));
  8. stuTS.add(new Student("张平",3));
  9. //使用迭代器循环输出
  10. Iterator it = stuTS.iterator();
  11. while (it.hasNext()) {
  12. System.out.println(it.next());
  13. }
  14. }
  15. }

3.2 Set接口 - 图3


图3.5 Comparable接口的使用