当前位置:   article > 正文

Java中的Set系列集合超详解_set集合

set集合

 Set

 List是有序集合的根接口,Set是无序集合的根接口,无序也就意味着元素不重复。更严格地说,Set集合不包含一对元素e1和e2 ,使得e1.equals(e2) ,并且最多一个空元素。
  使用Set存储的特点与List相反:元素无序、不可重复。常用的实现方式:HashSet、LinkedHashSet和TreeSet。

Set系列集合概述和特点

  • 底层数据结构是哈希表

  • 存取无序

  • 不可以存储重复元素

  • 没有索引,不能使用普通for循环遍历

set集合的基本应用

  1. public static void main(String[] args) {
  2. Set<String> s=new HashSet<String>();
  3. boolean flag1= s.add("aaa");
  4. boolean flag2 = s.add("aaa");
  5. System.out.println(flag1);
  6. System.out.println(flag2);
  7. System.out.println(s);
  8. //如果当前元素是第一次添加,那么可以添加成功,返回true
  9. //如果当前元素是第二次添加,那么添加失败,返回false
  10. }

        

存储字符串并遍历

方式一迭代器方式

  1. public static void main(String[] args) {
  2. Set<String> s=new HashSet<String>();
  3. s.add("张三");
  4. s.add("李四");
  5. //迭代器
  6. Iterator<String> it = s.iterator();
  7. while(it.hasNext()){
  8. String str = it.next();
  9. System.out.println(str);
  10. }
  11. }

方式2-增强for

  1. //增强for
  2. for (String str : s) {
  3. System.out.println(str);
  4. }

方式3lambda表达式

  1. // Lambda表达式
  2. s.forEach((String str)-> System.out.println(str));

总结

HashSet集合概述和特点

  • 底层数据结构是哈希表

  • 存取无序

  • 不可以存储重复元素

  • 没有索引,不能使用普通for循环遍历

哈希值

  • 哈希值简介

    是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

  • 如何获取哈希值

    Object类中的public int hashCode():返回对象的哈希码值

  • 哈希值的特点

    • 同一个对象多次调用hashCode()方法返回的哈希值是相同的

    • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

  1. package set;
  2. /*
  3. 哈希值:
  4. 对象的整数表现形式
  5. 1. 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
  6. 2. 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
  7. 3. 但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)
  8. */
  9. public class demo3 {
  10. public static void main(String[] args) {
  11. // 1. 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
  12. Student s1 = new Student("zhangsan",18);
  13. Student s2 = new Student("zhangsan",18);
  14. /* System.out.println(s1.hashCode());//189568618
  15. System.out.println(s2.hashCode());//793589513*/
  16. //不一样,所以我们要重写hashCode()
  17. // 2. 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样
  18. System.out.println("------------------");
  19. System.out.println(s1.hashCode());//1461067297
  20. System.out.println(s2.hashCode());//1461067297
  21. // 3. 但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)
  22. //哈希碰撞
  23. System.out.println("abc".hashCode());//96354
  24. System.out.println("acD".hashCode());//96354
  25. }
  26. }

练习

  1. package lx;
  2. import java.util.HashSet;
  3. public class demo1 {
  4. public static void main(String[] args) {
  5. Student s1 = new Student("张三", 8);
  6. Student s2 = new Student("张三", 8);
  7. Student s3 = new Student("李四", 18);
  8. Student s4 = new Student("王五", 17);
  9. HashSet<Student> set = new HashSet<Student>();
  10. set.add(s1);
  11. set.add(s2);
  12. set.add(s3);
  13. set.add(s4);
  14. //重写hashCode方法就可以去重复的对象
  15. //因为重写hashCode方法,比的是属性值,属性值一样,哈希值一样,所以添加不成功
  16. //不重写比的是地址值,创建出来的对象地址值永远不一样,所以哈希值不一样,所以添加成功
  17. //如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样
  18. //重写equals方法也一样 比的也是地址值,不是属性值
  19. for (Student student : set) {
  20. System.out.println(student);
  21. }
  22. }
  23. }

注意像String Integer类型的,Java已经在底层重写好了HashSet和equals方法

LinkedHashSet

  1. package LinkedHashSet;
  2. import lx.Student;
  3. import java.util.HashSet;
  4. import java.util.LinkedHashSet;
  5. public class demo1 {
  6. public static void main(String[] args) {
  7. Student s1 = new Student("张三", 8);
  8. Student s2 = new Student("张三", 8);
  9. Student s3 = new Student("李四", 18);
  10. Student s4 = new Student("王五", 17);
  11. LinkedHashSet<Student> set = new LinkedHashSet<Student>();
  12. set.add(s3);
  13. set.add(s1);
  14. set.add(s3);
  15. set.add(s4);
  16. //LinkedHashSet的存和去顺序一样
  17. for (Student student : set) {
  18. System.out.println(student);
  19. }
  20. }
  21. }

 

TreeSet

  1. package TreeSet;
  2. import java.util.TreeSet;
  3. public class demo1 {
  4. public static void main(String[] args) {
  5. //利用TreeSet对整数进行排序
  6. //默认升序
  7. TreeSet<Integer> ts = new TreeSet<>();
  8. //添加元素
  9. ts.add(4);
  10. ts.add(2);
  11. ts.add(5);
  12. ts.add(8);
  13. ts.add(1);
  14. //使用增强for
  15. for (Integer t : ts) {
  16. System.out.print(t + " ");
  17. }
  18. }
  19. }

  1. package TreeSet;
  2. import java.util.TreeSet;
  3. public class demo2 {
  4. public static void main(String[] args) {
  5. //利用TreeSet对String类型进行排序
  6. TreeSet<String> ts = new TreeSet<>();
  7. ts.add("va");
  8. ts.add("aaa");
  9. ts.add("ha");
  10. ts.add("aba");
  11. ts.add("acd");
  12. for (String t : ts) {
  13. System.out.print(t + " ");
  14. }
  15. }
  16. }

练习

  1. @Override
  2. public int compareTo(Student o) {
  3. //只看年龄按照升序排序
  4. int tmp=this.getAge() - o.getAge();
  5. tmp= tmp==0?this.getName().compareTo(o.getName()):tmp;
  6. return tmp;
  7. }
  1. package TreeSet;
  2. import javax.print.DocFlavor;
  3. import java.util.TreeSet;
  4. import java.util.function.Consumer;
  5. public class demo3 {
  6. public static void main(String[] args) {
  7. //利用TreeSet对学生类型进行排序
  8. TreeSet<Student> ts = new TreeSet<>();
  9. //要求: 按照学生的年龄进行排序
  10. //同年按照姓名字母排序
  11. //同姓名,同年龄认为同一个人
  12. Student s1 = new Student("zhangsan", 18);
  13. Student s2 = new Student("lisi", 19);
  14. Student s3 = new Student("wangwu", 19);
  15. ts.add(s2);
  16. ts.add(s3);
  17. ts.add(s1);
  18. System.out.println(ts);
  19. //方式一:默认的排序方式,Student实现一个接口(comparable接口)重写里面的抽象方法
  20. //再指定比较规则
  21. //hashCode和equals方法跟哈希表有关
  22. //TreeSet底层红黑树有关
  23. //所以不需要重写hashCode和equals方法
  24. }
  25. }

  1. package TreeSet;
  2. import java.util.Comparator;
  3. import java.util.TreeSet;
  4. public class demo4 {
  5. public static void main(String[] args) {
  6. //方法二:比较器排序
  7. //1.创建集合
  8. //2.o1表示当前要添加的元素
  9. //3.o2表示已经在红黑树存在的元素
  10. //返回值规则跟之前一样
  11. TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
  12. @Override
  13. /*
  14. 需求:请自行选择比较器排序和自然排序两种方式;
  15. 要求:存入四个字符串, “c”, “ab”, “df”, “qwer”
  16. 按照长度排序,如果一样长则按照首字母排序
  17. 采取第二种排序方式:比较器排序
  18. */
  19. public int compare(String o1, String o2) {
  20. //按照长度来
  21. int tmp = o1.length() - o2.length();
  22. //如果一样长则按照首字母排序
  23. tmp = tmp == 0 ? o1.compareTo(o2) : tmp;
  24. return tmp;
  25. }
  26. });
  27. //2.添加元素
  28. ts.add("c");
  29. ts.add("ab");
  30. ts.add("df");
  31. ts.add("qwer");
  32. System.out.println(ts);
  33. }
  34. }

  1. package lx2;
  2. import java.util.TreeSet;
  3. /* 需求:创建5个学生对象
  4. 属性:(姓名,年龄,语文成绩,数学成绩,英语成绩),
  5. 按照总分从高到低输出到控制台
  6. 如果总分一样,按照语文成绩排
  7. 如果语文一样,按照数学成绩排
  8. 如果数学成绩一样,按照英语成绩排
  9. 如果英文成绩一样,按照年龄排
  10. 如果年龄一样,按照姓名的字母顺序排
  11. 如果都一样,认为是同一个学生,不存。
  12. 第一种:默认排序/自然排序
  13. 第二种:比较器排序
  14. 默认情况下,用第一种排序方式,如果第一种不能满足当前的需求,采取第二种方式。
  15. 课堂练习:
  16. 要求:在遍历集合的时候,我想看到总分。
  17. */
  18. public class demo1 {
  19. public static void main(String[] args) {
  20. //1.创建学生对象
  21. Student s1 = new Student("zhangsan", 23, 90, 99, 50);
  22. Student s2 = new Student("lisi", 24, 90, 98, 50);
  23. Student s3 = new Student("wangwu", 25, 95, 100, 30);
  24. Student s4 = new Student("zhaoliu", 26, 60, 99, 70);
  25. Student s5 = new Student("qianqi", 26, 70, 80, 70);
  26. TreeSet<Student> st=new TreeSet<>();
  27. st.add(s1);
  28. st.add(s2);
  29. st.add(s3);
  30. st.add(s4);
  31. st.add(s5);
  32. for (Student student : st) {
  33. System.out.println(student);
  34. }
  35. }
  36. }

  1. package lx2;
  2. //第一种:默认排序/自然排序
  3. public class Student implements Comparable<Student> {
  4. private String name;
  5. private int age;
  6. //语文成绩
  7. private int chinese;
  8. //数学成绩
  9. private int math;
  10. //英语成绩
  11. private int english;
  12. public Student() {
  13. }
  14. public Student(String name, int age, int chinese, int math, int english) {
  15. this.name = name;
  16. this.age = age;
  17. this.chinese = chinese;
  18. this.math = math;
  19. this.english = english;
  20. }
  21. /**
  22. * 获取
  23. *
  24. * @return name
  25. */
  26. public String getName() {
  27. return name;
  28. }
  29. /**
  30. * 设置
  31. *
  32. * @param name
  33. */
  34. public void setName(String name) {
  35. this.name = name;
  36. }
  37. /**
  38. * 获取
  39. *
  40. * @return age
  41. */
  42. public int getAge() {
  43. return age;
  44. }
  45. /**
  46. * 设置
  47. *
  48. * @param age
  49. */
  50. public void setAge(int age) {
  51. this.age = age;
  52. }
  53. /**
  54. * 获取
  55. *
  56. * @return chinese
  57. */
  58. public int getChinese() {
  59. return chinese;
  60. }
  61. /**
  62. * 设置
  63. *
  64. * @param chinese
  65. */
  66. public void setChinese(int chinese) {
  67. this.chinese = chinese;
  68. }
  69. /**
  70. * 获取
  71. *
  72. * @return math
  73. */
  74. public int getMath() {
  75. return math;
  76. }
  77. /**
  78. * 设置
  79. *
  80. * @param math
  81. */
  82. public void setMath(int math) {
  83. this.math = math;
  84. }
  85. /**
  86. * 获取
  87. *
  88. * @return english
  89. */
  90. public int getEnglish() {
  91. return english;
  92. }
  93. /**
  94. * 设置
  95. *
  96. * @param english
  97. */
  98. public void setEnglish(int english) {
  99. this.english = english;
  100. }
  101. public String toString() {
  102. return "Student{name = " + name + ", age = " + age + ", chinese = " + chinese + ", math = " + math + ", english = " + english + "}";
  103. }
  104. @Override
  105. public int compareTo(Student o) {
  106. /* 按照总分从高到低输出到控制台
  107. 如果总分一样,按照语文成绩排
  108. 如果语文一样,按照数学成绩排
  109. 如果数学成绩一样,按照英语成绩排
  110. 如果英文成绩一样,按照年龄排
  111. 如果年龄一样,按照姓名的字母顺序排
  112. 如果都一样,认为是同一个学生,不存。*/
  113. int sum1 = this.getChinese() + this.getMath() + this.getEnglish();
  114. int sum2=o.getChinese() + o.getMath() + o.getEnglish();
  115. int tmp = sum2-sum1;
  116. // 如果总分一样,按照语文成绩排
  117. tmp = tmp == 0 ? this.getChinese() - o.getChinese() : tmp;
  118. // 如果语文一样,按照数学成绩排
  119. tmp = tmp == 0 ? this.getMath() - o.getMath() : tmp;
  120. //如果数学成绩一样,按照英语成绩排
  121. tmp = tmp == 0 ? this.getEnglish() - o.getEnglish() : tmp;
  122. //如果英文成绩一样,按照年龄排
  123. tmp = tmp == 0 ? this.getAge() - o.getAge() : tmp;
  124. // 如果年龄一样,按照姓名的字母顺序排
  125. tmp = tmp == 0 ? this.getName().compareTo(o.getName()) : tmp;
  126. return tmp;
  127. }
  128. }

TreeSet二种排序方式

  1. public class test {
  2. public static void main(String[] args) {
  3. TreeSet<String> ts = new TreeSet<>((o1, o2) -> o1.compareTo(o2));
  4. ts.add("c");
  5. ts.add("ab");
  6. ts.add("df");
  7. ts.add("qwer");
  8. System.out.println(ts);//默认是通过Stirng排序方法,也就是说通过首字母排序的方法来的,不是根据长度来的
  9. }
  10. }

 

如果使用默认的排序方法,则不能满足需求,可以使用第二种排序方法,并定义规矩进行重写

排序的原理图:



总结

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/973919
推荐阅读
相关标签
  

闽ICP备14008679号