Java基础知识之TreeSet的使用

TreeSet是一个具有唯一元素的二叉树集合,同时TreeSet是Set接口的一个实现类(TreeSet实现了Set的接口),它具有Set的特点。

Set的特点有:不可重复,元素无顺序,没有带索引的方法(因此不能使用普通for循环来遍历,也不能通过索引来获取或删除Set集合中的元素值)。

TreeSet的特点:不可重复,没有带索引的方法(因此不能使用普通for循环来遍历,也不能通过索引来获取或删除TreeSet集合中的元素值),可以将元素按自定义规则进行排序。

接下来我们将从TreeSet的三个特点并结合代码来学习TreeSet。(由于TreeSet没有带索引的方法,因此TreeSet的第二个特点只能使用forEach语句与Iterator迭代器来实现TreeSet的遍历)

注意:TreeSet的默认数据类型是Object类,理论上我们可以通过add()方法来添加任意数据类型,但是如果我们这样子做,当我们进行遍历输出的时候就会遇到麻烦!!!因此我们在使用TreeSet的时候,请使用泛型来约束数据类型!!!

一、不可重复

数据类型为String类型的TreeSet,用普通输出语句来实现TreeSet元素的输出

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        //若要使用TreeSet,我们需要导入import java.util.TreeSet;
        //我们使用泛型来约束TreeSet的数据类型为String类型
        TreeSet<String> set=new TreeSet<>();
        //使用add()方法来添加数据
        set.add("aa");
        set.add("aa");
        set.add("bb");
        //打印
        System.out.println(set);
    }
}

运行结果(重复的aa元素被筛掉)
在这里插入图片描述


Integer类型的TreeSet,用普通输出语句来实现TreeSet元素的输出

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        //若要使用TreeSet,我们需要导入import java.util.TreeSet;
        //我们使用泛型来约束TreeSet的数据类型为Integer数据类型
        TreeSet<Integer> set=new TreeSet<>();
        //使用add()方法来添加数据
        set.add(18);
        set.add(20);
        set.add(20);
        //打印
        System.out.println(set);
    }
}

运行结果(重复的20元素被筛掉,TreeSet不可重复特点)
在这里插入图片描述


TreeSet操作自定义Student类型数据

Student类

//若要在TreeSet中遍历我们自定义的数据类,我们需要复写Comparable接口中的compareTo()方法
public class Student implements Comparable<Student>{
    
    
    private String name;
    private char gender;
    private int age;
    private double salary;
    //无参构造方法
    public Student() {
    
    }
    //全参构造方法
    public Student(String name, char gender, int age, double salary) {
    
    
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.salary = salary;
    }
    //Set,Get方法
    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        this.name = name;
    }
    public char getGender() {
    
    
        return gender;
    }
    public void setGender(char gender) {
    
    
        this.gender = gender;
    }
    public int getAge() {
    
    
        return age;
    }
    public void setAge(int age) {
    
    
        this.age = age;
    }
    public double getSalary() {
    
    
        return salary;
    }
    public void setSalary(double salary) {
    
    
        this.salary = salary;
    }
    //toString方法
    @Override
    public String toString() {
    
    
        return "Student{" +
                "name='" + name + '\'' +
                ", gender=" + gender +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
	//复写compareTo方法
    @Override
    public int compareTo(Student o) {
    
    
        return -1;
        //return的值不同,输出的结果就不同
        //若返回的结果是0,则只会返回第一个元素
        //若返回的结果是1,则会返回所有元素(按输入的顺序输出)
        //若返回的结果是-1,则会返回所有元素(按输入的顺序反向输出)
    }
}

Student类型的TreeSet,用forEach语句来实现TreeSet元素的遍历输出

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        //若要使用TreeSet,我们需要导入import java.util.TreeSet;
        //我们使用泛型来约束TreeSet的数据类型为Student类型
        TreeSet<Student> set=new TreeSet<>();
        //使用add()方法来添加数据
        set.add(new Student("zhangsan",'男',18,2500.00));
        set.add(new Student("lisi",'女',19,2600.00));
        set.add(new Student("wangwu",'男',20,3000.00));
        set.add(new Student("wangwu",'男',20,3000.00));
        //在此我们使用forEach来遍历TreeSet
        //Student是set的数据类型,我们将set的数据存入student(此名字你可以自定义)中并输出
        for(Student student:set){
    
    
            System.out.println(student);
        }
    }
}

Student类 return 0的输出
在这里插入图片描述


Student类 return 1的输出
我们发现这里输出的内容含有重复的值,其实这并没有违反TreeSet不可重复这一条件,这是因为我们实际上并没有真正重写Comparable接口中的compareTo()方法,在元素进行比较的时候,计算机并没有通过比较他们的值来判定他们是否不同,而是通过比较他们存储的内存地址来比较他们是否不同,而我们都知道在我们存储数据时,都会为元素开辟一个内存空间,而开辟的内存空间各个内存空间的地址肯定是不同的,因此计算机认为他们是不同的。
在这里插入图片描述


Student类 return -1的输出
我们发现这里输出的内容含有重复的值,其实这并没有违反TreeSet不可重复这一条件,这是因为我们实际上并没有真正重写Comparable接口中的compareTo()方法,在元素进行比较的时候,计算机并没有通过比较他们的值来判定他们是否不同,而是通过比较他们存储的内存地址来比较他们是否不同,而我们都知道在我们存储数据时,都会为元素开辟一个内存空间,而开辟的内存空间各个内存空间的地址肯定是不同的,因此计算机认为他们是不同的。
在这里插入图片描述


那么我们如何使得TreeSet存储的数据的值不可重复呢?下面我们来复写Comparable接口中的compareTo()方法

二、元素可以按我们自定义规则进行排序

Student类重写compareTo()方法(使用年龄排序,相同年龄不会存储,在这里我们规定数据按年龄进行排序,那么就相当于告诉计算机即使数据名字不同,年龄相同就认为它们就是相同的)

//复写compareTo方法,按年龄进行排序
    @Override
    public int compareTo(Student o) {
    
    
        //这里我们根据年龄来排序,当我们存入一个数据后,它就变成了this,之后我们再存入数据,此数据就是o
        //例如我们刚开始存入(zhangsan,18),那么此时this.age=18,之后我们存入(lisi,19),那么o.getAge()=19
        //所以此时result=18-19=-1<0,表明传入对象(o)年龄>this对象年龄,传入对象存入右边即(zhangsan,18),(lisi,19)
        //之后我们又传入(wangwu,20),那么它会先于(zhangsan,18)比较,再与(lisi,19)比较,最后形成(zhangsan,18),(lisi,19),(wangwu,20)
        //最后我们传入(chenliu,20),那么它会先于(zhangsan,18)比较,再与(lisi,19)比较,最后再与(wangwu,20)比较,result=18-18=0,年龄相同,计算机认为它们是重复的,不在存入
        int result=this.age-o.getAge();
        return result;
    }

Student类型的TreeSet,用forEach语句来实现TreeSet元素的遍历输出

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        //若要使用TreeSet,我们需要导入import java.util.TreeSet;
        //我们使用泛型来约束TreeSet的数据类型为Student类型
        TreeSet<Student> set=new TreeSet<>();
        //使用add()方法来添加数据
        set.add(new Student("zhangsan",'男',18,2500.00));
        set.add(new Student("lisi",'女',19,2600.00));
        set.add(new Student("wangwu",'男',20,3000.00));
        set.add(new Student("chenliu",'男',20,3000.00));
        //在此我们使用forEach来遍历TreeSet
        //Student是set的数据类型,我们将set的数据存入student(此名字你可以自定义)中并输出
        for(Student student:set){
    
    
            System.out.println(student);
        }
    }
}

运行结果:(可以看到wangwu与chenliu名字不同,但是年龄相同,计算机也会认为他们重复)
在这里插入图片描述


Student类重写compareTo()方法(使用年龄与姓名进行排序,相同年龄,排名字,名字与年龄若均相同,计算机则会认为数据重复)

//复写compareTo方法
    @Override
    public int compareTo(Student o) {
    
    
        //这里我们先根据年龄来排序,当我们存入一个数据后,它就变成了this,之后我们再存入数据,此数据就是o
        //例如我们刚开始存入(zhangsan,18),那么此时this.age=18,之后我们存入(lisi,19),那么o.getAge()=19
        //所以此时result=18-19=-1<0,表明传入数据>当前数据,传入元素存入右边即(zhangsan,18),(lisi,19)
        //之后我们又传入(wangwu,20),那么它会先于(zhangsan,18)比较,再与(lisi,19)比较,最后形成(zhangsan,18),(lisi,19),(wangwu,20)
        //最后我们传入(chenliu,20),那么它会先于(zhangsan,18)比较,再与(lisi,19)比较,最后再与(wangwu,20)比较,年龄相同,对名字进行排序
        int result=this.age-o.getAge();
        
        //下面的语句指出,如果result==0(即年龄相同),则执行this.name.compareTo(o.getName())对名字进行排序,否则(年龄不同)执行result(按年龄排序),并将最终结果存储在变量中。
        //那么这样wangwu与chenliu的年龄相同时,会比较他们的姓名,名字不同,因此计算机会将它们视为不同对象,并根据它们的姓名进行排序
        result = result==0 ? this.name.compareTo(o.getName()) :result;
        return result;
    }

Student类型的TreeSet,用forEach语句来实现TreeSet元素的遍历输出

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        //若要使用TreeSet,我们需要导入import java.util.TreeSet;
        //我们使用泛型来约束TreeSet的数据类型为Student类型
        TreeSet<Student> set=new TreeSet<>();
        //使用add()方法来添加数据
        set.add(new Student("zhangsan",'男',18,2500.00));
        set.add(new Student("lisi",'女',19,2600.00));
        set.add(new Student("wangwu",'男',20,3000.00));
        set.add(new Student("chenliu",'男',20,3000.00));
        //在此我们使用forEach来遍历TreeSet
        //Student是set的数据类型,我们将set的数据存入student(此名字你可以自定义)中并输出
        for(Student student:set){
    
    
            System.out.println(student);
        }
    }
}

运行结果:(可以看到wangwu与chenliu均输出)
在这里插入图片描述


三、使用Iterator迭代器来实现TreeSet元素遍历输出

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        //若要使用TreeSet,我们需要导入import java.util.TreeSet;
        //我们使用泛型来约束TreeSet的数据类型为String类型
        TreeSet<String> set=new TreeSet<>();
        //使用add()方法来添加数据
        set.add("aa");
        set.add("aa");
        set.add("bb");
        //在此我们使用Iterator迭代器来遍历TreeSet
        //创建迭代器对象
        Iterator<String> iterator=set.iterator();
        //判断该位置是否有值,iterator.hasNext()它会查看我们当前位置是否存在元素,存在元素返回true,不存在元素返回false
        while(iterator.hasNext()){
    
    
        	//获取该位置的元素值,iterator.next()它会取得我们目前位置的元素,然后指针后移
            System.out.println(iterator.next());
        }
    }
}

运行结果:(不可重复)
在这里插入图片描述


OK! TreeSet的这三大特点的运用就介绍完毕!

猜你喜欢

转载自blog.csdn.net/qq_45344586/article/details/129680447