Java之TreeSet集合(二叉树实现)以及Comparable接口介绍

TreeSet 集合类是Set的子类
固有保持数据不重复的属性,除此之外还有一个独有的功能就是排序
当然常见的Integer,String类中java都将其比较机制写的很完善了
但对于自定义类而言 ,想要去排序就要自己去实现了
假设录入一个 Person类 (new Person(“aa”,100))其属性为姓名和年龄
假设要求我需要对集合中Person的年龄进行排序的话 我们该怎么办呢?
TreeSet集合排序和保证元素唯一的原理
别着急 下面我们介绍一下Comparbale接口
实现这个接口就要重写 public int compareTo(Object o)方法
返回值是一个int值
对于这个方法有如下特性
前提保证返回值为固定值
1.当返回值为0 表示不存入集合
2.当返回值为正数 表示存入集合(功能为按照你存的顺序 正向存储)
3.当返回值为负数 表示存入集合(功能为按照你存的顺序 逆向存储)
至于为什么 下面我就介绍一下TreeSet中底层的实现算法二叉树
二叉树的实现就是说
第一个进来的数据 (对象)作为根
然后随后进来的对象依次与根进行比较
如果小于对象就放左边
如果大于对象就放右边
如果相等就不存储
在这里插入图片描述
希望这张图能更加深理解
这是重写了compareTo方法来比较年龄
所以返回从左开始 13 23 33 43

这是通过先比较名字的长度 然后再去比较名字的内容(跟拼音和笔画没有关系 全是靠Unicode编码实现的) 最后比较年龄

public class Person implements Comparable<Person> {

//......之前的属性和行为省略
/*@Override
	//按照年龄排序
	public int compareTo(Person o) {
		int num = this.age - o.age;				//年龄是比较的主要条件
		return num == 0 ? this.name.compareTo(o.name) : num;//姓名是比较的次要条件
	}*/
	/*@Override
	//按照姓名排序
	public int compareTo(Person o) {
		int num = this.name.compareTo(o.name);		//姓名是主要条件
		return num == 0 ? this.age - o.age : num;	//年龄是次要条件
	}*/
	/*
	 * aaa
	 * bbb
	 */
	public int compareTo(Person o) {
		int length = this.name.length() - o.name.length();				//比较长度为主要条件
		int num = length == 0 ? this.name.compareTo(o.name) : length;	//比较内容为次要条件
		return num == 0 ? this.age - o.age : num;						//比较年龄为次要条件
	}
}

TreeSet实现排序的第二种原理
比较器 原理其实和第一种差不多 稍微改变的只是代码 方便对于java已有排序的类进行改进(Integer ,String之类)
在这里插入图片描述

自定义比较器代码
1.实现Comparator的接口
2.重写compare方法 (由于每个类都是Object的子类 所以不需要重写equals方法)

class CompareByLen /*extends Object*/ implements Comparator<String> {

	@Override
	public int compare(String s1, String s2) {		//按照字符串的长度比较
		int num = s1.length() - s2.length();		//长度为主要条件
		return num == 0 ? s1.compareTo(s2) : num;	//内容为次要条件
	}
	
}

3.最后在把比较器当作引用参数传递给TreeSet

TreeSet<String> ts = new TreeSet<>(new CompareByLen());		//Comparator c = new CompareByLen();

具体代码:

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

import com.heiam.bean.Person;

public class Demo3_TreeSet {

	/**
	 * @param args
	 * TreeSet集合是用来对象元素进行排序的,同样他也可以保证元素的唯一
	 * 当compareTo方法返回0的时候集合中只有一个元素
	 * 当compareTo方法返回正数的时候集合会怎么存就怎么取
	 * 当compareTo方法返回负数的时候集合会倒序存储
	 */
	public static void main(String[] args) {
		//需求:将字符串按照长度排序
		TreeSet<String> ts = new TreeSet<>(new CompareByLen());		//Comparator c = new CompareByLen();
		ts.add("aaaaaaaa");
		ts.add("z");
		ts.add("wc");
		ts.add("nba");
		ts.add("cba");
		System.out.println(ts);
	}
}


class CompareByLen /*extends Object*/ implements Comparator<String> {

	@Override
	public int compare(String s1, String s2) {		//按照字符串的长度比较
		int num = s1.length() - s2.length();		//长度为主要条件
		return num == 0 ? s1.compareTo(s2) : num;	//内容为次要条件
	}
	
}

下面谈两种比较方法的区别
一丶自然排序(Comparable)
1.TreeSet中的add方法会自动把传入的对象提升为Comparable类型(如果没有提升的话 就会报出类型转换异常)
2.调用传入对象中的comparaTo()方法和集合中已有的对象作比较
3.根据comparaTo()方法的返回值的结果进行存储
二丶比较器Comparator< E >
1.创建TreeSet对象的时候可以传入一个比较器Comparator< E >
2.如果传入Comparator< E >d的子类对象,那么TreeSet就会按照比较器中的比较顺序排序
3.add()方法是自动调用Comparator< E >中compare方法

两种方式的区别
1.自然排序 TreeSet的无参构造
2.比较器排序 TreeSet的有参构造(参数为Comparator< E >)

小练习1.保留重复 并且排序
由于都知道要储存重复数据 需要用到ArrayList来存储
如果排序则需要TreeSet

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

public class Main{
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<>();
		list.add("b");
		list.add("b");
		list.add("a");
		list.add("a");
		list.add("a");
		System.out.println(list);
		sort(list);	
		System.out.println(list);
	}

	public static void sort(ArrayList<String> list) {
	//匿名内部类!!!!
		TreeSet<String> ts = new TreeSet<>(
		new Comparator<String>(){
			@Override
			public int compare(String s1, String s2) {
				int num = s1.compareTo(s2);
				return num == 0 ? 1 : num;
			}
		});	
		
		ts.addAll(list);
		list.clear();
		list.addAll(ts);
	}
}

如果不用匿名内部类的话 感觉比较复杂不是很方便

public class Main{
	public static void main(String[] args) {
		TreeSet<String> ts = new TreeSet<>(new  Comcom());		//Comparator c = new CompareByLen();
	}
}
class Comcom implements Comparator<String>{
		
	@Override
	public int compare(String s1, String s2) {
		int num = s1.compareTo(s2);
		return num == 0 ? 1 : num;
	}
	
}

打印的结果
在这里插入图片描述

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑瞳丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值