java set comparable_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 {

//......之前的属性和行为省略

/*@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 {

@Override

public int compare(String s1, String s2) {        //按照字符串的长度比较

int num = s1.length() - s2.length();        //长度为主要条件

return num == 0 ? s1.compareTo(s2) : num;    //内容为次要条件

}

}

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

TreeSet 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 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 {

@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 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 list) {

//匿名内部类!!!!

TreeSet ts = new TreeSet<>(

new Comparator(){

@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 ts = new TreeSet<>(new  Comcom());        //Comparator c = new CompareByLen();

}

}

class Comcom implements Comparator{

@Override

public int compare(String s1, String s2) {

int num = s1.compareTo(s2);

return num == 0 ? 1 : num;

}

}

打印的结果  啊

/* * 二叉树节点ADT接口 */ package dsa; public interface BinTreePosition extends Position { //判断是否有父亲(为使代码描述简洁) public boolean hasParent(); //返回当前节点的父节点 public BinTreePosition getParent(); //设置当前节点的父节点 public void setParent(BinTreePosition p); //判断是否为叶子 public boolean isLeaf(); //判断是否为左孩子(为使代码描述简洁) public boolean isLChild(); //判断是否有左孩子(为使代码描述简洁) public boolean hasLChild(); //返回当前节点的左孩子 public BinTreePosition getLChild(); //设置当前节点的左孩子(注意:this.lChild和c.parent都不一定为空) public void setLChild(BinTreePosition c); //判断是否为右孩子(为使代码描述简洁) public boolean isRChild(); //判断是否有右孩子(为使代码描述简洁) public boolean hasRChild(); //返回当前节点的右孩子 public BinTreePosition getRChild(); //设置当前节点的右孩子(注意:this.rChild和c.parent都不一定为空) public void setRChild(BinTreePosition c); //返回当前节点后代元素的数目 public int getSize(); //在孩子发生变化后,更新当前节点及其祖先的规模 public void updateSize(); //返回当前节点的高度 public int getHeight(); //在孩子发生变化后,更新当前节点及其祖先的高度 public void updateHeight(); //返回当前节点的深度 public int getDepth(); //在父亲发生变化后,更新当前节点及其后代的深度 public void updateDepth(); //按照中序遍历的次序,找到当前节点的直接前驱 public BinTreePosition getPrev(); //按照中序遍历的次序,找到当前节点的直接后继 public BinTreePosition getSucc(); //断绝当前节点与其父亲的父子关系 //返回当前节点 public BinTreePosition secede(); //将节点c作为当前节点的左孩子 public BinTreePosition attachL(BinTreePosition c); //将节点c作为当前节点的右孩子 public BinTreePosition attachR(BinTreePosition c); //前序遍历 public Iterator elementsPreorder(); //中序遍历 public Iterator elementsInorder(); //后序遍历 public Iterator elementsPostorder(); //层次遍历 public Iterator elementsLevelorder(); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值