Java---28---Set集合之TreeSet

TreeSet :可以对Set集合中的元素进行排序

排序是按照ascii来排序的。


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


public class TreeSetDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		method1();
	}


	public static void method1() {
		TreeSet ts = new TreeSet();
		ts.add("cba");
		ts.add("aaa");
		ts.add("bca");
		ts.add("abcd");

		Iterator it = ts.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
		/**
		 * 打印结果是: aaa abcd bca cba treeset中元素是有顺序的 是按照ascii码来排序的
		 */

	}

}

自定义类Student,中有属性name和age,按照age 从小到大排序。

 

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


class Student {
	private String name;
	private int age;

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

	// set and get methods
	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) {
		// TODO Auto-generated method stub
		TreeSet ts = new TreeSet();
		ts.add(new Student("01", 10));
		ts.add(new Student("02", 15));
		ts.add(new Student("03", 9));
		ts.add(new Student("04", 18));
		
		Iterator it = ts.iterator();
		while (it.hasNext()){
			Student student = (Student) it.next();
			System.out.println(student.getName() +"::::"+student.getAge());
		}
	}

}

运行发现出现错误:


Exception in thread "main" java.lang.ClassCastException: Student cannot be cast to java.lang.Comparable
	at java.util.TreeMap.compare(TreeMap.java:1290)
	at java.util.TreeMap.put(TreeMap.java:538)
	at java.util.TreeSet.add(TreeSet.java:255)
	at TreeSetDemo.main(TreeSetDemo.java:39)


因为TreeSet是一个有序的集合,它要知道它里边的元素是如何进行排列的,所以需要Student类实现Comparable接口.

 

Comparable接口强行实现它的每个类的对象进行整体排序,这种排序被称为自然排序。此接口中只有一个方法compareToxuyao 复写。



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



class Student implements Comparable{
	private String name;
	private int age;

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

	// set and get methods
	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 int compareTo(Object o) {
		if (!(o instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student student = (Student) o;
		if (this.age > student.age)
			return 1;
		if (this.age == student.age)
			return 0;
		return -1;
	}

}

public class TreeSetDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TreeSet ts = new TreeSet();
		ts.add(new Student("01", 10));
		ts.add(new Student("02", 15));
		ts.add(new Student("03", 9));
		ts.add(new Student("04", 18));
		
		Iterator it = ts.iterator();
		while (it.hasNext()){
			Student student = (Student) it.next();
			System.out.println(student.getName() +"::::"+student.getAge());
		}
	}

}

通过复写这个方法,可以打印出结果:


03::::9
01::::10
02::::15
04::::18


但是当添加一个与已有元素年龄相同但是姓名不同的元素却添加不上。。

我们加上这么一个元素

ts.add(new Student("05", 18));

但是显示结果却没有它。因为在这个compareTo方法中认为年龄相同的就是同一个元素,为此,当年龄相同时我们还要再做一次判断,判断其姓名是否也相同。


我们将compareTo方法修改如下:

public int compareTo(Object o) {
		if (!(o instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student student = (Student) o;
		if (this.age > student.age)
			return 1;
		if (this.age == student.age) {
			return this.name.compareTo(student.name);
		}
		return -1;
	}


再次运行就会发现,05元素存入到集合中了。那么TreeSet 是如何进行比较的呢?

我们在compareTo方法中添加这么一句:

System.out.println(this.name + "-----compaerTo-----" + student.name);

用来显示其运行过程。

public int compareTo(Object o) {
		if (!(o instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student student = (Student) o;
		System.out.println(this.name + "-----compaerTo-----" + student.name);
		if (this.age > student.age)
			return 1;
		if (this.age == student.age) {
			return this.name.compareTo(student.name);
		}
		return -1;
	}

运行结果:

02-----compaerTo-----01
03-----compaerTo-----01
04-----compaerTo-----01
04-----compaerTo-----02
05-----compaerTo-----01
05-----compaerTo-----02
05-----compaerTo-----04
03::::9
01::::10
02::::15
04::::18
05::::18

通过这个结果,我们可了解到此程序的运行过程:

首先,01先存入

02与01进行比较,存入

03与01比较,存入

04与01 02 比较 存入

05和01 02 04比较 存入

 

为什么是这个样子的呢?为什么不是和此元素之前的所有元素进行比较呢?就是因为TreeSet的底层数据结构是二叉树。

技术分享


我们根据此程序画了一张图,当第一个元素存入的时候,为此元素创建一个节点10(年龄),此后的元素在存入的时候,会跟10这个节点进行比较,比他小的在它左边创建一个节点,比他大的在它右边创建节点,以此类推,如04存入的时候,先跟10比较,比10大,应该存放到右边,但是右边有元素15,再跟15比较,比15大,在15的右边创建节点,存入。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。