JAVAday17 Set集合

本文深入讲解Java中的Set集合,包括HashSet、LinkedHashSet和TreeSet的特点与用法。探讨了HashSet如何确保元素唯一性,LinkedHashSet如何保持插入顺序,以及TreeSet如何实现自然排序和比较器排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JAVAday17 Set集合

一 set集合概述

set集合之下有三个子类分别是

1.HashSet 底层数据结构是哈希表(数组+链表+二叉树)

​ 元素无序(存取的顺序不一致),且元素唯一

2.LinkedHashSet 底层数据结构是哈希表和链表

​ 元素有序,且唯一

3.TreeSet 底层数据结构是二叉树

​ 元素唯一且可以对元素进行排序

二 HashSet, LinkedHashSet, TreeSet用法

2.1 HashSet如何保证元素的唯一性

当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
HashSet 集合判断两个元素相等的标准:

两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。

结论:HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。

public class MyTest {
    public static void main(String[] args) {
        //HashSet 之所以能够保证元素的唯一性,是靠元素重写 equals()方法,来保证的,如果元素不重写该方法,则不能保证元素的唯一性
        //合理重写hashCode 方法,是为了减少调用equals()的次数,也称之为减少碰撞

        Student s1 = new Student("zhangsan", 19);
        Student s2 = new Student("lisi", 19);
        Student s3 = new Student("zhnagwu", 19);
        Student s4 = new Student("liuqi", 20);
        Student s5 = new Student("liuba", 23);
        Student s6 = new Student("zhangsan", 19);
        Student s7 = new Student("wnagwu", 19);
        HashSet<Student> students = new HashSet<>();
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        students.add(s5);
        students.add(s6);
        students.add(s7);
        //重写equals方法
        public boolean equals(Object obj){
            ifthis == obj){
                return ture;
            }
            if(!obj instanceof Student{
                return false
            }
            Student stu = (Student)obj;
             return this.name.equalsIgnoreCase(stu.name)&&this,age==stu.age;//完成去重
        }
        // 重写hascode方法
        public int hashCode{
            return this.name.hashCode()+this.age*10;
        }
        for (Student student : students) {
          System.out.println(student);
             
    }
2.2 LinkedHashSet的用法

链表保证元素有序,哈希表保证唯一

public class MyTest2 {
    public static void main(String[] args) {
        //LinkedHashSet 底层数据结构是链表和哈希表  元素有序且唯一  链表保证了有序,哈希表保证了唯一
        //线程不安全效率高
        LinkedHashSet<String> strings = new LinkedHashSet<>();
        strings.add("aaa");
        strings.add("bbb");
        strings.add("ccc");
        strings.add("ddd");
        strings.add("eee");
        strings.add("fff");
        strings.add("aaa");
        strings.add("bbb");
        strings.add("ccc");
        strings.add("ddd");
        strings.add("eee");
        strings.add("fff");
        for (String string : strings) {
            System.out.println(string);
        }


        ArrayList<String> strings1 = new ArrayList<>();
        strings1.add("aaaaa");
        strings1.add("bbbbb");
        strings1.add("ccc");
        strings1.add("dddd");
        strings1.add("eeee");
        strings1.add("aaaaa");
        strings1.add("bbbbb");
        strings1.add("ccc");
        strings1.add("dddd");
        strings1.add("eeee");
        HashSet<String> strings2 = new HashSet<>(strings1);
        System.out.println(strings2);


        LinkedHashSet<String> strings3 = new LinkedHashSet<>(strings1);
        System.out.println(strings3);
    }
}
2.3 TreeSet集合的用法

TreeSet 排序方法有两种 1:自然排序 2:使用比较器排序

​ 具体使用哪一种取决于构造方法

2.3.1 自然排序

二叉树的数据结构: 先存入一个树根 分两个叉,存储元素时 跟树根比较 小的放在左边 大的放在右边
如果相等就不存储,取的时候按照 左中右的顺序来取。

使用TreeSet集合进行自然排序时,要求元素必须实现Comparable接口,否则无法进行自然排序

保证元素唯一性是靠重写compare to方法的返回值来确定,如果返回0表示两个数相等,否则不重复存储。

public class MyTest {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>();

        treeSet.add(new Student("张三士大夫士大夫", 23));
        treeSet.add(new Student("张三是非得失", 23));
        treeSet.add(new Student("李四大幅度发", 23));
        treeSet.add(new Student("王五大幅度发", 20));
        treeSet.add(new Student("周六的", 30));
        treeSet.add(new Student("田七大幅度", 23));
        treeSet.add(new Student("李白大幅度发", 33));
        treeSet.add(new Student("刘星大幅度发", 63));
        treeSet.add(new Student("夏雨", 78));
        treeSet.add(new Student("张子豪", 53));
        
        

        for (Student student : treeSet) {
            System.out.println(student);
        }


    }
//实现comparable接口
public class Student implements Comparable<Student> {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //这是一个比较的方法
    @Override
    //重写compareTo接口
    public int compareTo(Student student) {
        //根据学生的年龄大小来排序
        //年龄一样,并不能说明是同一个对象,我们还得比较姓名是否一样

       int num=this.age-student.age;

        int num2=num==0?this.name.compareTo(student.name):num;


        return -num2; //根据返回值的正 负 0 来决定元素的放置位置
    }
}
2.3.2 比较器排序

采用有参构造,在创建TreeSet对象时Comparetor 比较器

public class MyTest {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>();

        treeSet.add(new Student("张三士大夫士大夫", 23));
        treeSet.add(new Student("张三是非得失", 23));
        treeSet.add(new Student("李四大幅度发", 23));
        treeSet.add(new Student("王五大幅度发", 20));
        treeSet.add(new Student("周六的", 30));
        treeSet.add(new Student("田七大幅度", 23));
        treeSet.add(new Student("李白大幅度发", 33));
        treeSet.add(new Student("刘星大幅度发", 63));
        treeSet.add(new Student("夏雨", 78));
        treeSet.add(new Student("张子豪", 53));
        //可以写一下实际类或通过匿名内部类传入
        TreeSet<Student>treeSet = new TreeSet<>(new Comparator<Student>);
            public int compare(Student s1,Student s2){
               int num = s1.getAge() - s2.getAge();
        	   int num2=num==0?s1.getName().compareTo(s2.getName()):num;
				 return num2;
        }
        

        for (Student student : treeSet) {
            System.out.println(student);
        }


    }
public class Student  {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
 
}
//构造一个实际类
public class MyComparator implements Comparator<Student> {
    @Override
    public int compare(Student s1, Student s2) {
        //按照年龄大小排序
        int num = s1.getAge() - s2.getAge();
        int num2=num==0?s1.getName().compareTo(s2.getName()):num;


        return num2;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值