Java集合框架——TreeSet集合

TreeSet 集合

一、API文档中的TreeSet集合
在这里插入图片描述

  • 使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。

二、TreeSet集合的特性

  • 元素唯一
  • 可以排序(根据创建TreeSet集合时使用的构造器选择以下两种方法之一)
    • 自然排序
    • 比较器(Comparator)排序

三、TreeSet集合的自然排序

  • 构造方法:TreeSet()
  • 构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。
package com.treeset.demo;

import java.util.TreeSet;

public class TreeSetTest {
	public static void main(String[] args) {
		TreeSet<Integer> treeset = new TreeSet<Integer>();
		
		treeset.add(10);
		treeset.add(8);
		treeset.add(11);
		treeset.add(3);
		treeset.add(1);
		treeset.add(9);
		
		for (Integer integer : treeset) {
			System.out.println(integer);
		}
	}
}
***执行结果:***
1
3
8
9
10
11

四、TreeSet集合的数据结构

五、TreeSet集合自然排序原理
(五~十将完整展现TreeSet集合自然排序的原理和方法实现)

  • 当添加第一个元素进TreeSet集合中时,把这个元素作为根节点
  • 当后面再有元素插入进来时,就会和节点进行比较
    • 大的放右边
    • 小的放左边
    • 如果一样就不添加(去重)
      在这里插入图片描述
  • 按照一种特殊的遍历树的方式进行遍历,得到的结果就是有序的,遍历二叉树的方式有三种:
    • 前序遍历
    • 中序遍历
    • 后序遍历
  • 这里按照前序遍历的方式就能使得到的结果是有序的
    • 若二叉树为空则结束返回,否则:
    • ① 访问根结点
    • ② 前序遍历左子树
    • ③ 前序遍历右子树
    • 需要注意的是:遍历左右子树时仍然采用前序遍历方法

六、案例实操一:实现学生类对象

//Student.java
package com.treeset.demo;

public class Student {
	private String name;
	private int age;
	
	public Student(String name, int i) {
		super();
		this.name = name;
		this.age = i;
	}
	
	public Student() {
		super();
	}

	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 + "]";
	}
}
//TreeSetTest2.java
package com.treeset.demo;

import java.util.TreeSet;

public class TreeSetTest2 {
	public static void main(String[] args) {
		TreeSet<Student> treeset = new TreeSet<Student>();
		
		Student stu1 = new Student("张三", 18);
		Student stu2 = new Student("李四", 19);
		Student stu3 = new Student("王五", 20);
		
		treeset.add(stu1);
		treeset.add(stu2);
		treeset.add(stu3);
	}
}
  • 执行后出现类型转换异常的报错:
  • Exception in thread “main” java.lang.ClassCastException: class com.treeset.demo.Student cannot be cast to class java.lang.Comparable
  • Student类无法转换成lang包下的Comparable接口

七、Comparable接口

  • 此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
  • 因此,只有实现了该接口的对象才算是具有自然排序的特性
    在这里插入图片描述
  • 上面第三大点(TreeSet集合的自然排序)中的代码可以进行自然排序的原因是Integer类已经实现了Comparable接口,从而使其对象具有可比较性
    在这里插入图片描述

八、Comparable接口的方法

  • int compareTo(T o) :比较此对象与指定对象的顺序

对象是如何通过Comparable接口的compareTo(T)方法进行排序的?

  • 查看Integer的源码中的compareTo方法以及compare方法
    在这里插入图片描述
	public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }

    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }
  • x(this.value)为当前对象,y(anotherInteger.value)为被比较的对象
  • compare方法比较时会产生三种情况:
    • x==y 返回0
    • x<y 返回-1(存储在树节点的左边)
    • x>y 返回1(存储在树节点的右边)
	public static void main(String[] args) {
		Integer i1 = 10;
		Integer i2 = 20;
		Integer i3 = 20;
		
		System.out.println(i1.compareTo(i2));  // -1
		System.out.println(i2.compareTo(i1));  // 1
		System.out.println(i2.compareTo(i3));  // 0
	}

九、案例实操二:向TreeSet集合添加字符串对象

package com.treeset.demo;

import java.util.TreeSet;

public class TreeSetTest4 {
	public static void main(String[] args) {
		TreeSet<String> treeset = new TreeSet<String>();
		
		treeset.add("abcde");
		treeset.add("fghij");
		treeset.add("fghij");
		treeset.add("faaaa");
		treeset.add("klmno");
		
		for (String str : treeset) {
			System.out.println(str);
		}
	}
}
***执行结果:***
abcde
faaaa
fghij
klmno
  • String类有自己的compareTo方法按照字典顺序来排序

十、如何让案例实操一的Student对象具有可比较性

  • Student类实现Comparable接口
  • 重写compareTo()方法
  • 完整代码:
//Student.java
package com.treeset.demo2;

public class Student implements Comparable<Student>{
	private String name;
	private int age;
	
	public Student(String name, int i) {
		super();
		this.name = name;
		this.age = i;
	}
	
	public Student() {
		super();
	}

	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
	public int compareTo(Student s) {
		//主要比较条件:年龄
		int num = this.age - s.getAge();
		//次要比较条件:名字
		int num2 = num==0 ? this.name.compareTo(s.getName()) : num;
		return num2;
	}
}
//TreeSetTest.java
package com.treeset.demo2;

import java.util.TreeSet;

public class TreeSetTest {
	public static void main(String[] args) {
		TreeSet<Student> set = new TreeSet<Student>();
		
		Student stu1 = new Student("张三", 19);
		Student stu2 = new Student("李四", 19);
		Student stu3 = new Student("王五", 20);
		
		set.add(stu1);
		set.add(stu2);
		set.add(stu3);
		
		for (Student stus : set) {
			System.out.println(stus);
		}
	}
}
***执行结果:***
Student [name=张三, age=19]
Student [name=李四, age=19]
Student [name=王五, age=20]

十一、使用比较器对TreeSet集合进行排序

  • 构造方法:TreeSet(Comparator<? super E> comparator)
  • 构造一个新的空 TreeSet,它根据指定比较器进行排序
  • API文档中的Comparator接口
    在这里插入图片描述
  • 利用TreeSet集合的比较器进行比较排序的步骤:
  • 创建比较器对象(实现Comparator接口的对象)
  • 使用带有比较器的TreeSet构造方法创建集合
  • 完整代码:
//Student.java
package com.treeset.demo3;

public class Student {
	private String name;
	private int age;
	
	public Student(String name, int i) {
		super();
		this.name = name;
		this.age = i;
	}
	
	public Student() {
		super();
	}

	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 + "]";
	}
}
//MyComparator.java
package com.treeset.demo3;

import java.util.Comparator;

public class MyComparator implements Comparator<Student> {
	@Override
	public int compare(Student s1, Student s2) {
		//主要比较条件:年龄
		int num1 = s1.getAge() - s2.getAge();
		//次要比较条件:名字
		int num2 = num1==0 ? s1.getName().compareTo(s2.getName()) : num1;
		return num2;
	}
}
//TreeSetTest.java
package com.treeset.demo3;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetTest {
	public static void main(String[] args) {
		//创建比较器对象
		Comparator<Student> comparator = new MyComparator();
		
		TreeSet<Student> set = new TreeSet<Student>(comparator);
		
		Student stu1 = new Student("张三", 18);
		Student stu2 = new Student("李四", 20);
		Student stu3 = new Student("王五", 20);
		
		set.add(stu1);
		set.add(stu2);
		set.add(stu3);
		
		for (Student stus : set) {
			System.out.println(stus);
		}
	}
}
***执行结果:***
Student [name=张三, age=18]
Student [name=李四, age=20]
Student [name=王五, age=20]

十二、匿名内部类实现比较器对象
在这里插入图片描述

TreeSet<Student> set = new TreeSet<Student>(new Comparator<Student>() {
			@Override
			public int compare(Student s1, Student s2) {
				int num1 = s1.getAge() - s2.getAge();
				int num2 = num1==0 ? s1.getName().compareTo(s2.getName()) : num1;
				return num2;
			}
		});
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值