java数据结构18_TreeSet类详解

TreeSet底层实际是用TreeMap实现的,内部维持了一个简化版的TreeMap,通过key来存储HashSet的元素。由于map中key都是不可重复的,因此,TreeSet天然具有“不可重复”的特性。

我们打开TreeSet的源码,发现里面有一行核心代码:
在这里插入图片描述
TreeMap是NavigableMap(基于红黑树)的实现类,而TreeSet底层使用NavigableMap来保存元素,所以说TreeSet内部维持了一个简化版的TreeMap,通过key来存储元素。

  • TreeSet****的使用

TreeSet是用来排序的,可以指定一个顺序,对象存入之后会按照指定的顺序排列,TreeSet中的元素支持2种排序方式:

  • 自然排序:通过实现Comparerable接口 ,并且重写compareTo方法。

TreeSet类的add()方法中会把存入的对象提升为Comparable类型, 调用对象的compareTo() 方 法和集合中的对象比较(当前存入的是谁,谁就会调用compareTo方法),根据compareTo() 方法返回的结果进行存储。

  • 比较器排序:通过实现Comparetor接口,并且重写compare方法。

创建TreeSet的时候可以制定一个Comparator,如果传入了Comparator的子类对象,那么TreeSet 就会按照比较器中的顺序排序。add()方法内部会自动调用Comparator接口中compare()方法排 序。调用的对象(就是当前存入的对象)是compare方法的第一个参数,集合中的对象(已经 添加进去的对象)是compare方法的第二个参数。

  • 自然排序

给TreeSet 中存储 JavaAPI 中提供的类型元素时,不需要实现Comparerable接口,因为在 JavaAPI 的每个类中已经重写完毕,如 String 类、Integer 类等,默认排序为升序。

【示例】HashSet存储 String

// 实例化一个TreeSet对象
TreeSet<String> set = new TreeSet<String>();
// 添加元素
set.add("bbb");
set.add("ccc");
set.add("aaa");
set.add("eee");
set.add("ddd");
set.add("eee");  // 只能输出一个“eee”
// 遍历元素
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
	System.out.println(iterator.next());
}

默认排序输出结果如下(两个“eee”只输出一个):

aaa
bbb
ccc
ddd
eee

给 HashSet 中存放自定义类型元素时,需要实现Comparerable接口并重写compareTo方法,否则抛出java.lang.ClassCastException异常。

【示例】创建自定义对象 Person

class Person implements Comparable<Person> {
	String name;
	int age;
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	// 重写compareTo方法
	@Override
	public int compareTo(Person o) {
		return this.age - o.age;
	}
}

因为TreeSet要对元素进行排序,那你排序的依据是什么,姓名还是年龄还是其它的,得告诉它,怎么告诉?需要让Person类实现Comparable接口并重写compareTo方法。

当compareTo方法返回值为负数,表示放在红黑树的左边,即逆序(降序)输出。

当compareTo方法返回值为零,表示元素相同,仅存放第一个元素(保证元素的唯一)。

当compareTo方法返回值为正数,表示放在红黑树的右边,即顺序(升序)输出。

【示例】创建 TreeSet 集合,存储 Person 对象

public class TreeSetDemo {
	public static void main(String[] args) {
		// 实例化一个TreeSet对象
		TreeSet<Person> set = new TreeSet<Person>();
		// 添加元素
		set.add(new Person("张三", 23));
		set.add(new Person("李四", 31));
		set.add(new Person("王五", 24)); 
		set.add(new Person("赵六", 31));
set.add(new Person("王麻子", 27));
		// 遍历元素
		Iterator<Person> iterator = set.iterator();
		while(iterator.hasNext()) {
			Person p = iterator.next();
			System.out.println("name:" + p.name + " age:" + p.age);
		}
	}
}

自定义排序输出结果如下:

name:张三 age:23
name:王五 age:24
name:王麻子 age:27
name:李四 age:31

注意:因为compareTo方法按照年龄进行排序,而“李四”和“赵六”年龄相同,所以后添加的“赵六”就无法保存(唯一性)。

  • 比较器排序

TreeSet构造方法什么都不传,默认按照类中Comparable的顺序排序(没有就抛出ClassCastException异常),当TreeSet的构造方法如果传入Comparator对象,就优先按照Comparator接口的compare方法进行排序。

当compare方法返回值为负数,表示放在红黑树的左边,即逆序(降序)输出。

当compare方法返回值为零,表示元素相同,仅存放第一个元素(保证元素的唯一)。

当compare方法返回值为正数,表示放在红黑树的右边,即顺序(升序)输出。

【示例】使用Comparator实现升序排序

// Student类
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;
	}
}
// 测试类
public class TreeSetDemo {
	public static void main(String[] args) {
		// 实例化一个set对象,并按照年龄进行升序
	Set<Student> set = new TreeSet<Student>(new Comparator<Student>() {
			@Override // 按照年龄进行比较排序
			public int compare(Student o1, Student o2) {
				return o1.getAge() - o2.getAge();
			}
		});
		// 添加元素
		set.add(new Student("张三", 23));
		set.add(new Student("李四", 31));
		set.add(new Student("王五", 24));
		set.add(new Student("赵六", 31));
		set.add(new Student("王麻子", 27));
		// 遍历set
		Iterator<Student> iterator = set.iterator();
		while (iterator.hasNext()) {
			Student stu = iterator.next();
			System.out.println("name:" + stu.getName() + " age:" + stu.getAge());
		}
	}
}

自定义排序输出结果如下:

name:张三 age:23
name:王五 age:24
name:王麻子 age:27
name:李四 age:31

注意:因为compare方法按照年龄进行排序,而“李四”和“赵六”年龄相同,所以后添加的“赵六”就无法保存(唯一性)。

  • 使用TreeSet要点:
  1. 由于是二叉树,需要对元素做内部排序。所以要么实现Comparable接口,要么实现Comparator接口,否则会抛出java.lang.ClassCastException异常。

  2. TreeSet中不能放入null元素,否则抛出java.lang.NullPointerException异常。

ps:如需最新的免费文档资料和教学视频,请添加QQ群(627407545)领取。

发布了35 篇原创文章 · 获赞 0 · 访问量 350

猜你喜欢

转载自blog.csdn.net/zhoujunfeng121/article/details/104562250