java集合框架之TreeSet类

1.TreeSet介绍

TreeSet集合底层采用红黑树算法,会对存储的元素默认使用自然排序(从小到大).
注意: 必须保证TreeSet集合中的元素对象是相同的数据类型,否则报错.


2.TreeSet的排序规则

自然排序(从小到大):
TreeSet调用集合元素的compareTo方法来比较元素的大小关系,然后将集合元素按照升序排列(从小到大).
注意:要求TreeSet集合中元素得实现java.util.Comparable接口.

各种数据类型自然排序规则


java.util.Comparable接口:可比较的.
覆盖 public int compareTo(Object o)方法,在该方法中编写比较规则.
在该方法中,比较当前对象(this)和参数对象o做比较(严格上说比较的是对象中的数据,比如按照对象的年龄排序).
       this  >  o: 返回正整数.  1
       this <   o: 返回负整数.  -1
       this == o: 返回0.     此时认为两个对象为同一个对象.
--------------------------------------
在TreeSet的自然排序中,认为如果两个对象做比较的compareTo方法返回的是0,则认为是同一个对象.


从上图可知,基本上很多类都实现了这个接口,我们来看一下String类源码,可以看出String已经实现Comparable,并覆盖compareTo方法



举例:

import java.util.Set;
import java.util.TreeSet;

public class SetDemo4 {
	public static void main(String[] args) {
		Set<String> set = new TreeSet<>();
		
		set.add("a");
		set.add("A");
		set.add("abc");
		set.add("B");
		
		System.out.println(set);//打印结果,已经排好序了[A, B, a, abc],按照字符串的Unicode值排序
	}
}
在这里我们如果要想自己定义的类在TreeSet中也能实现自然排序,那么就要根据上面的步骤来实现:

举个例子:首先定义一个Student类,这个类要实现Comparable接口,然后覆盖CompareTo方法,自定义自己需要排序的规则,比如我们这里按照学生的姓名的长度进行自然排序:

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

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}

	/**
	 * 覆盖compareTo方法
	 * 根据学生的姓名长度排序
	 */
	public int compareTo(Student stu) {
		if (this.getName().length()>stu.getName().length()) {
			return 1; 
		}else if (this.getName().length()<stu.getName().length()) {
			return -1;
		}else {
			return 0; //长度相同
		}
	}
	
}
测试:打印结果,姓名长度由短到长来排序的

import java.util.Set;
import java.util.TreeSet;

public class SetDemo4 {
	public static void main(String[] args) {
		Set<Student> set = new TreeSet<>();
		
		set.add(new Student(1, "聂小倩"));
		set.add(new Student(1, "西门吹雪"));
		set.add(new Student(1, "哥"));
		set.add(new Student(1, "孙斌"));
		
		System.out.println(set);
		//打印结果看下面,说明是按照名字长度从小到大的自然顺序来排序的
		//[Student [id=1, name=哥], Student [id=1, name=孙斌], Student [id=1, name=聂小倩], Student [id=1, name=西门吹雪]]
	}
}


定制排序(比如从大到小,按照名字的长短来排序):
TreeSet构造器中传递java.lang.Comparator对象.覆盖public int compare(Object o1, Object o2)再编写比较规则.

在TreeSet构造函数中,有一个构造函数可以传入一个比较器对象,他是一个接口,我们需要提供实现类,并覆盖compare方法再编写比较规则.


同样的,我们举个例子,也是按照学生姓名长度排序:

首先也是定义一个学生类:

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

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}	
}
然后定义比较器类:

import java.util.Comparator;

//比较器类
class NameLengthComparator implements Comparator<Student> {
	/**
	 * 覆盖compare方法
	 * 比较规则:同样是根据学生的姓名长度排序
	 */
	public int compare(Student s1, Student s2) {
		if (s1.getName().length() > s2.getName().length()) {
			return 1;
		} else if (s1.getName().length() < s2.getName().length()) {
			return -1;
		} else {
			return 0;
		}
	}

}
测试:

import java.util.Set;
import java.util.TreeSet;

public class SetDemo5 {
	public static void main(String[] args) {
		//创建set对象的时候要传入比较器类对象
		Set<Student> set = new TreeSet<>(new NameLengthComparator());

		set.add(new Student(1, "聂小倩"));
		set.add(new Student(1, "西门吹雪"));
		set.add(new Student(1, "哥"));
		set.add(new Student(1, "孙斌"));

		System.out.println(set);
	}
}
打印结果:

[Student2 [id=1, name=哥], Student2 [id=1, name=孙斌], Student2 [id=1, name=聂小倩], Student2 [id=1, name=西门吹雪]]

既然是定制排序,你可以修改排序规则,按照从长到短来排序,只需要修改比较器类的实现规则

import java.util.Comparator;

//比较器类
class NameLengthComparator implements Comparator<Student> {
	/**
	 * 覆盖compare方法
	 * 比较规则:同样是根据学生的姓名长度排序
	 */
	public int compare(Student s1, Student s2) {
		if (s1.getName().length() < s2.getName().length()) {
			return 1;
		} else if (s1.getName().length() > s2.getName().length()) {
			return -1;
		} else {
			return 0;
		}
	}

}
将if中的>和<修改一下就行了

对于TreeSet集合来说,要么使用自然排序,要么使用定制排序.
判断两个对象是否相等的规则:
自然排序:   compareTo方法返回0;
定制排序:  compare方法返回0;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值