Java集合 TreeSet实现详解

本文深入讲解了Java中TreeSet的两种排序方式:自然排序和定制排序。自然排序通过实现Comparable接口并重写compareTo方法实现,而定制排序则通过实现Comparator接口并重写compare方法实现。文章提供了详细的代码示例。

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

TreeSet实现详解
TreeSet是SortedSet接口的实现类,所以可以看出TreeSet是有序的。
与HashSet集合采用hash算法来决定元素的存储位置不同,TreeSet采用红黑树的数据结构来存储集合元素,那么TreeSet进行排序的规则是怎样的?TreeSet支持两种排序:自然排序和定制排序。

1、自然排序
TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系,然后将集合元素按升序排列,这种方式就是自然排序
如果试图将元素添加到TreeSet集合中,只有第一个元素无须实现Comparable接口,后面添加的元素都必须实现该接口,但是这样会引发ClassCastException。所以在将元素添加到集合之前,应该将该对象实现Comparable接口。当实现了该接口时,添加元素时,会自动调用compareTo(Object obj)方法,这就要求集合中的其他元素与该元素是同一个类的对象。
当一个对象调用该方法与另一个对象进行比较时,如:obj1.compareTo(obj2),如果该方法返回0,说明两者相等;如果返回时一个正数,说明obj1 > obj2;如果返回一个负数,表明 obj1< obj2;

简单例子1:


/*
	通过姓名进行升排序
*/
package com.microtao.set;

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

class Person implements Comparable {
	private String name;
	private int age;
	private String sex;

	public Person() {
	}

	public Person(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	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 String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}

	/*
	 * 重写compareTo方法进行比较
	 */
	@Override
	public int compareTo(Object o) {
		Person p = (Person) o;
		if (this.name.compareTo(p.name) > 0) {
			return 1;
		}
		if (this.name.compareTo(p.name) < 0) {
			return -1;
		}
		return this.name.compareTo(p.name);
	}

}

public class TreeSetTest {
	public static void main(String[] args) {
		Set ts = new TreeSet();
		ts.add(new Person("as", 17, "男"));
		ts.add(new Person("qeq", 32, "男"));
		ts.add(new Person("21sd", 53, "男"));
		ts.add(new Person("sc", 33, "男"));
		ts.add(new Person("sa", 33, "男"));
		
		Iterator it = ts.iterator();
		while (it.hasNext()) {

			System.out.println(it.next());
		}
	}

}
运行结果:
		Person [name=21sd, age=53, sex=]
		Person [name=as, age=17, sex=]
		Person [name=qeq, age=32, sex=]
		Person [name=sa, age=33, sex=]
		Person [name=sc, age=33, sex=]

简单例子2:


/*
	通过年龄进行升排序
*/
package com.microtao.set;

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

class Person implements Comparable {
	private String name;
	private int age;
	private String sex;

	public Person() {
	}

	public Person(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	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 String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}
/*
	 * 重写compareTo方法按照年龄进行升排序
	 */
	@Override
	public int compareTo(Object o) {
		Person p = (Person) o;
		if(this.age > p.age ) {
			return 1;
		}
		if(this.age < p.age ) {
			return -1;
		}
		return this.name.compareTo(p.name);
	}

}

public class TreeSetTest {
	public static void main(String[] args) {
		Set ts = new TreeSet();
		ts.add(new Person("as", 17, "男"));
		ts.add(new Person("qeq", 32, "男"));
		ts.add(new Person("21sd", 53, "男"));
		ts.add(new Person("sc", 33, "男"));
		ts.add(new Person("sa", 33, "男"));
		
		Iterator it = ts.iterator();
		while (it.hasNext()) {

			System.out.println(it.next());
		}
	}

}
运行结果:
		Person [name=as, age=17, sex=]
		Person [name=qeq, age=32, sex=]
		Person [name=sa, age=33, sex=]
		Person [name=sc, age=33, sex=]
		Person [name=21sd, age=53, sex=]

2、定制排序
当元素自身不具备比较性,或者自身具备的比较性不是所需要的,那么此时可以让容器自身具备。需要定义一个类实现Comparator,重写compare方法,并将该接口的实现类作为参数传递给TreeMap集合构造方法。

**注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主。**在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较的次要条件。

简单例子:

package com.microtao.set;

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

class P{
	private String name;
	private int age;
	private String sex;
	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 String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public P(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}
	
}

/**  实现Comparator接口,并将两个对象进行比较
 * 	  首先依据年龄进行排序,如果年龄相等的话,并不表示他是同一个人,其次会对姓名进行排序,如果姓名也是一样的话
 *    表明这两个对象是同一个对象,只有一个该对象被加入到集合中。
 * @author Microtao
 *
 */
class MyComparator implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		Person p1 = (Person) o1;
		Person p2 = (Person) o2;
		if(p1.getAge() > p2.getAge()) {
			return 1;
		}
		if(p1.getAge() < p2.getAge()) {
			return -1;
		}
		return p1.getName().compareTo(p2.getName());
	}
	
}
public class TreeSetTest2 {

	public static void main(String[] args) {
		TreeSet ts = new TreeSet(new MyComparator());
		ts.add(new Person("ada",52,"男"));
		ts.add(new Person("dwdd",12,"男"));
		ts.add(new Person("fds",32,"男"));
		ts.add(new Person("gs",5,"男"));
		ts.add(new Person("gc",5,"男"));
		Iterator it = ts.iterator();
		while (it.hasNext()) {

			System.out.println(it.next());
		}
	}
}
	运行结果:
	Person [name=gc, age=5, sex=]
	Person [name=gs, age=5, sex=]
	Person [name=dwdd, age=12, sex=]
	Person [name=fds, age=32, sex=]
	Person [name=ada, age=52, sex=]

总结:

  • TreeSet是一个有序的集合,基于TreeMap实现,支持两种排序方式:自然排序和定制排序。主要是实现Comparable接口重写comparaTo()方法,与实现Comparator接口,重写compare(Obj o1,Obj o2),并将其实现类作为参数传递给TreeSet。
  • TreeSet是非同步的,线程不安全。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值