第四讲 Set 一、概述 Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。 |--HashSet:底层数据结构是哈希表。线程不同步。 保证元素唯一性的原理:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true。 |--TreeSet:可以对Set集合中的元素进行排序。默认按照字母的自然排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0。 Set集合的功能和Collection是一致的。 二、HasSet HashSet:线程不安全,存取速度快。 可以通过元素的两个方法,hashCode和equals来完成保证元素唯一性。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals。 注意:HashSet对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。 示例: - 1. /*
- 2. 往hashSet集合中存入自定对象
- 3. 姓名和年龄相同为同一个人,重复元素。去除重复元素
- 4. 思路:1、对人描述,将人的一些属性等封装进对象
- 5. 2、定义一个HashSet容器,存储人对象
- 6. 3、取出
- 7.
- 8. */
- 9. import java.util.*;
- 10.
- 11. //人描述
- 12. class Person
- 13. {
- 14. private String name;
- 15. private int age;
- 16.
- 17. Person(String name,int age)
- 18. {
- 19. this.name=name;
- 20. this.age=age;
- 21. }
- 22.
- 23. public String getName()
- 24. {
- 25. return name;
- 26. }
- 27.
- 28. public int getAge()
- 29. {
- 30. return age;
- 31. }
- 32.
- 33. public boolean equals(Object obj)
- 34. {
- 35. if(!(obj instanceof Person))
- 36. return false;
- 37. Person p=(Person)obj;
- 38. return this.name.equals(p.name)&&this.age==p.age;
- 39. }
- 40.
- 41. public int hashCode()
- 42. {
- 43. return this.name.hashCode()+this.age;
- 44. }
- 45. }
- 46. class HashSetTest
- 47. {
- 48. public static void main(String[] args)
- 49. {
- 50. HashSet h=new HashSet();
- 51. h.add(new Person("shenm",10));
- 52. h.add(new Person("shenm2",6));
- 53. h.add(new Person("shenm1",30));
- 54. h.add(new Person("shenm0",10));
- 55. h.add(new Person("shenm0",10));
- 56.
- 57. getOut(h);
- 58.
- 59. }
- 60.
- 61. //取出元素
- 62. public static void getOut(HashSet h)
- 63. {
- 64. for (Iterator it=h.iterator(); it.hasNext(); )
- 65. {
- 66. Person p=(Person)it.next();
- 67. sop(p.getName()+"..."+p.getAge());
- 68. }
- 69. }
- 70.
- 71. //打印
- 72. public static void sop(Object obj)
- 73. {
- 74. System.out.println(obj);
- 75. }
- 76. }
复制代码三、TreeSet 1、特点 a、底层的数据结构为二叉树结构(红黑树结构) b)可对Set集合中的元素进行排序,是因为:TreeSet类实现了Comparable接口,该接口强制让增加到集合中的对象进行了比较,需要复写compareTo方法,才能让对象按指定需求(如人的年龄大小比较等)进行排序,并加入集合。 java中的很多类都具备比较性,其实就是实现了Comparable接口。 注意:排序时,当主要条件相同时,按次要条件排序。 二叉树示意图 file:///C:/Users/dou/AppData/Roaming/Tencent/Users/281665334/QQ/WinTemp/RichOle/Q%7DJ$T$6XPECKF)A4(ILZ%60PT.jpg
c、保证数据的唯一性的依据:通过compareTo方法的返回值,是正整数、负整数或零,则两个对象较大、较小或相同。相等时则不会存入。 2、Tree排序的两种方式 1)第一种排序方式:自然排序 让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也被称为元素的自然顺序,或者叫做默认顺序。 示例: - 1. import java.util.*;
- 2. //学生类
- 3. class Student implements Comparable
- 4. {
- 5. private String name;
- 6. private int age;
- 7. Student(String name,int age)
- 8. {
- 9. this.name=name;
- 10. this.age=age;
- 11. }
- 12. public String getName()
- 13. {
- 14. return name;
- 15. }
- 16.
- 17. public int getAge()
- 18. {
- 19. return age;
- 20. }
- 21. //复写hashCode以便HashSet集合调用
- 22. public int hashCode()
- 23. {
- 24. return name.hashCode()+age;
- 25. }
- 26. //复写equals以便HashSet集合和集合中一些比较方法调用
- 27. public boolean equals(Object obj)
- 28. {
- 29. if(!(obj instanceof Student))
- 30. throw new RuntimeException();
- 31. Student s = (Student)obj;
- 32. return this.name.equals(s.name)&&this.age==s.age;
- 33. }
- 34. //复写compareTo以便TreeSet集合调用
- 35. public int compareTo(Object obj)
- 36. {
- 37. Student s=(Student)obj;
- 38. if(this.age==s.age)
- 39. return this.name.compareTo(s.name);
- 40. return this.age-s.age;
- 41. //return new Integer(this.age).compareTo(new Integer(s.age));
- 42. }
- 43. }
- 44.
- 45. class TreeSetTest
- 46. {
- 47. public static void main(String[] args)
- 48. {
- 49. TreeSet<Student> t=new TreeSet<Student>();
- 50. t.add(new Student("wo1",12));
- 51. t.add(new Student("wosj",2));
- 52. t.add(new Student("wo1sdj",12));
- 53. t.add(new Student("wo6sd",12));
- 54. t.add(new Student("wo",22));
- 55.
- 56.
- 57. for (Iterator<Student> it=t.iterator(); it.hasNext(); )
- 58. {
- 59. Student s=it.next();
- 60. System.out.println(s.getName()+"....."+s.getAge());
- 61. }
- 62. }
- 63. }
复制代码2)第二种方式:比较器 当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。 在集合初始化时,就有了比较方式。定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。 比较器构造方式:定义一个类,实现Comparator接口,覆盖compare方法。 当两种排序都存在时,以比较器为主。 示例: - 1. /*
- 2. 需求:
- 3. 往TreeSet集合中存储自定义对象学生。
- 4. 想按照学生的年龄进行排序。
- 5.
- 6. */
- 7.
- 8. import java.util.*;
- 9. //学生类
- 10. class Student implements Comparable
- 11. {
- 12. private String name;
- 13. private int age;
- 14. Student(String name,int age)
- 15. {
- 16. this.name=name;
- 17. this.age=age;
- 18. }
- 19. public String getName()
- 20. {
- 21. return name;
- 22. }
- 23.
- 24. public int getAge()
- 25. {
- 26. return age;
- 27. }
- 28. //复写hashCode以便HashSet集合调用
- 29. public int hashCode()
- 30. {
- 31. return name.hashCode()+age;
- 32. }
- 33. //复写equals以便HashSet集合和集合中一些比较方法调用
- 34. public boolean equals(Object obj)
- 35. {
- 36. if(!(obj instanceof Student))
- 37. throw new RuntimeException();
- 38. Student s = (Student)obj;
- 39. return this.name.equals(s.name)&&this.age==s.age;
- 40. }
- 41. //复写compareTo以便TreeSet集合调用
- 42. public int compareTo(Object obj)
- 43. {
- 44. Student s=(Student)obj;
- 45. if(this.age==s.age)
- 46. return this.name.compareTo(s.name);
- 47. return this.age-s.age;
- 48. //return new Integer(this.age).compareTo(new Integer(s.age));
- 49. }
- 50.
- 51. }
- 52.
- 53. class TreeSetTest
- 54. {
- 55. public static void main(String[] args)
- 56. {
- 57. TreeSet<Student> t=new TreeSet<Student>(new LenCompare());
- 58. t.add(new Student("wo1",12));
- 59. t.add(new Student("wosj",2));
- 60. t.add(new Student("wo1sdj",12));
- 61. t.add(new Student("wo6sd",12));
- 62. t.add(new Student("wo",22));
- 63.
- 64.
- 65. for (Iterator<Student> it=t.iterator(); it.hasNext(); )
- 66. {
- 67. Student s=it.next();
- 68. System.out.println(s.getName()+"....."+s.getAge());
- 69. }
- 70. }
- 71.
- 72. }
- 73. //定义一个比较器,以姓名长度为主要比较
- 74. class LenCompare implements Comparator<Student>
- 75. {
- 76. public int compare(Student s1,Student s2)
- 77. {
- 78. int num=new Integer(s1.getName().length()).compareTo(new Integer(s2.getName().length()));
- 79. if (num==0)
- 80. {
- 81. return new Integer(s1.getAge()).compareTo(s2.getAge());
- 82. }
- 83. return num;
- 84. }
- 85. }
复制代码
|