• 你不知道的Set集合


    本期精彩:

    Set接口

    基本介绍

    Set接口的实现类

    1、HashSet

    特点 

    HashSet的实现

    代码知识 

    2、TreeSet

    特点

    代码知识


    Set接口

    基本介绍

    特点:

    • Set:无序(存入和取出的循序不同故不能使用下标遍历),不重复
    • List:有序,元素不可重复

    遍历:foreach,迭代器

    扩容: 初始容量16,负载因子0.75,扩容增量1倍

    Set、Queue、List都属于Collection

     ThreeSet与Collection等关系的UML图

    看不明白这个图中的关系箭头的可以去看一下这篇博客,里面详细介绍了UML图👇👇
    List集合&UML图_小阿飞_的博客-CSDN博客UML图一看就懂的秘诀 and List接口中的集合你了解多少?https://blog.csdn.net/yifei_345678/article/details/125483171?spm=1001.2014.3001.5501

    Set接口的实现类

    Set和List集合一样属于接口,无法直接创建实例化对象,需要实现类来创建,HashSet、ThreeSet都是常用的实现类

    1、HashSet

    特点 

    • 非线程安全
    • HashMap支持
    • 不保证插入顺序
    • 存在于java.util包中的类同时也被称为集合,该容器中只能存储不重复的对象
    • 它存储唯一元素并允许空值(依据对象的hashcode来确定该元素是否存在)
    • 性能参数:初始容量,负载因子(默认值: 初始容量16,负载因子0.75

    HashSet的实现

    对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,我们应该为保存到 HashSet 中的对象覆盖 hashCode() 和 equals()

    已知实现接口有:

    Serializable, Cloneable, Iterable<E>, Collection<E>, Set<E>

    已知子类:

    JobStateReasons, LinkedHashSet

    代码知识 

    曾经有一道题,问如何把ArrayList中重复的元素去掉(去重),方法有很多,小猿们可以自己试着写几个,这里提供一个比较简单快速的方法:使用HashSet去重👇

    1. public class SetDemo {
    2. private List<Integer> list = new ArrayList<>();
    3. @BeforeAll
    4. public void setup() {
    5. set.add(1);
    6. set.add(1);
    7. set.add(2);
    8. set.add(2);
    9. set.add(3);
    10. set.add(3);
    11. }
    12. @Test
    13. public void test01() {
    14. List<Integer> tmp = new ArrayList<>(new HashSet<Integer>(list));
    15. System.out.println(tmp);
    16. }
    17. }

    👆输出结果是123(ArrayList是可以存放重复元素的,但是这里使用了HashSet去重) 

    1、新建一个Set集合并放入元素👇

    1. public class SetDemo {
    2. private Set<Integer> set = new HashSet<>();
    3. @BeforeAll
    4. public void setup() {
    5. set.add(1);
    6. set.add(1);
    7. set.add(2);
    8. set.add(4);
    9. set.add(5);
    10. set.add(3);
    11. }
    12. }

    2、可以使用下面两种方法遍历其中的元素,由于HashSet中只能存储不重复的对象,所以输出时会自动把重复的元素去重👇 

    1. @Test
    2. public void test02() {
    3. for(Integer e: set) {
    4. System.out.println(e);
    5. }
    6. }
    7. //使用迭代器
    8. @Test
    9. public void test03() {
    10. Iterator<Integer> it = set.iterator();
    11. while(it.hasNext()) {
    12. System.out.println(it.next());
    13. }
    14. }

    3、set.remove(i)中传入的是元素,这是由于HashSet不保证插入顺序,没有下标概念,所以只能传入元素

    1. @Test
    2. public void test05() {
    3. set.remove(3);
    4. System.out.println(set);
    5. }

    👆删除的是第一步里面Set集合里面的元素3,输出的是1245 

    2、TreeSet

    特点

    • 是一个包含有序的且没有重复元素的集合
    • 作用是提供有序的Set集合,自然排序(比如123456...)或者根据提供的Comparator(比较器)进行排序
    • TreeSet是基于TreeMap实现的,而ThreeMap的底层是Map(键值对)

    代码知识

    创建一个学生类并实现编比较器接口

    1. public class Student implements Comparable<Student>{
    2. private Integer sid;
    3. private String sname;
    4. private int age;
    5. public Student(Integer sid, String sname, int age) {
    6. super();
    7. this.sid = sid;
    8. this.sname = sname;
    9. this.age = age;
    10. }
    11. public Integer getSid() {
    12. return sid;
    13. }
    14. public void setSid(Integer sid) {
    15. this.sid = sid;
    16. }
    17. public String getSname() {
    18. return sname;
    19. }
    20. public void setSname(String sname) {
    21. this.sname = sname;
    22. }
    23. public int getAge() {
    24. return age;
    25. }
    26. public void setAge(int age) {
    27. this.age = age;
    28. }
    29. }

    还需要在这个学生类中实现hashCodeequals方法:

    1. /*
    2. *hashCode可以将学号名字努力转成唯一的数字,相对于身份证
    3. */
    4. @Override
    5. public int hashCode() {
    6. final int prime = 31;
    7. int result = 1;
    8. result = prime * result + age;
    9. result = prime * result + ((sid == null) ? 0 : sid.hashCode());
    10. result = prime * result + ((sname == null) ? 0 : sname.hashCode());
    11. return result;
    12. }
    13. @Override
    14. public boolean equals(Object obj) {
    15. if (this == obj)
    16. return true;
    17. if (obj == null)
    18. return false;
    19. if (getClass() != obj.getClass())
    20. return false;
    21. Student other = (Student) obj;
    22. if (age != other.age)
    23. return false;
    24. if (sid == null) {
    25. if (other.sid != null)
    26. return false;
    27. } else if (!sid.equals(other.sid))
    28. return false;
    29. if (sname == null) {
    30. if (other.sname != null)
    31. return false;
    32. } else if (!sname.equals(other.sname))
    33. return false;
    34. return true;//学号名字年龄都相等才是同一个学生
    35. }
    36. @Override
    37. public String toString() {
    38. return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
    39. }
    40. /**
    41. * 实现Comparable<Student>接口后需要重写的方法
    42. * 根据年龄排序,年龄相同则比较学号,默认是升序
    43. */
    44. @Override
    45. public int compareTo(Student o) {
    46. if(this.getAge()-o.getAge()==0) {
    47. return this.getSid()-o.getSid();
    48. }
    49. return this.getAge() - o.getAge();
    50. }

    然后再使用ThreeSet👇

    1. @Test
    2. public void test04() {
    3. TreeSet<Student> stu = new TreeSet<>();
    4. stu.add(new Student(1,"zs", 18));
    5. stu.add(new Student(1,"zs", 18));
    6. stu.add(new Student(2,"ls", 19));
    7. stu.add(new Student(4,"lihao", 10));
    8. stu.add(new Student(7,"lihao", 18));
    9. stu.add(new Student(5,"zengfanyan", 20));
    10. stu.add(new Student(3,"we", 30));
    11. for(Student s: stu) {
    12. System.out.println(s);
    13. }
    14. }

    👆运行输出结果:

     

  • 相关阅读:
    初识Java 12-3 流
    发布https网页?用cpolar轻松做到
    观察者模式
    2022-11-21 mysql列存储引擎-缓存心血积累
    厉害了,腾讯云云巢荣获信通院“云原生技术创新案例”奖!
    Vivado关联Vscode,解决Vscode自动保存和卡顿问题
    SpringBoot集成JSR并使用
    一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?
    epoll比select和poll究竟高效在哪儿(剖析及实现)
    【MAPBOX基础功能】15、mapbox地图事件:点击、移入、移出、解绑
  • 原文地址:https://blog.csdn.net/yifei_345678/article/details/125495624