java treeset类的排序规则_Java 中 TreeSet 集合类排序方法

TreeSet是依靠TreeMap来实现的。TreeSet是一个有序集合,TreeSet中的元素将按照升序排列,缺省是按照自然排序进行排列,意味着TreeSet中的元素要实现Comparable接口。或者有一个自定义的比较器。TreeSet支持两种排序方法:自然排序和定制排序,TreeSet默认采用自然排序。

Java常用类实现Comparable接口,并提供了比较大小的标准。实现Comparable接口的常用类:BigDecimal、BigIneger以及所有数值型对应包装类:按它们对应的数值的大小进行比较;

Character:按字符的UNICODE值进行比较;

Boolean:true对应的包装类实例大于false对应的包装类实例;

String:按字符串中字符的UNICODE值进行比较;

Date、Time:后面的时间、日期比前面的时间、日期大。

1、添加一个对象到TreeSet时,对象类必须实现Comparable接口,代码如下:package com.yoodb;

import java.util.TreeSet;

public class Error{

public static void main(String[] args) {

TreeSet set = new TreeSet();

set.add(new Error());

set.add(new Error());

}

}

其结果报错,错误信息如下:Exception in thread "main" java.lang.ClassCastException: com.Error cannot be cast to java.lang.Comparable

at java.util.TreeMap.compare(TreeMap.java:1188)

at java.util.TreeMap.put(TreeMap.java:531)

at java.util.TreeSet.add(TreeSet.java:255)

at com.Error.main(Error.java:9)

注意:

1)如果向TreeSet集合中添加2个Error对象,添加第一个对象时,TreeSet里没有任何元素因此没有问题,但添加第二个Error对象时TreeSet就会调用该对象的compareTo(Object obj)方法与集合中其他元素进行比较,如果对应的类没有实现Comparable接口,则会引发ClassCastException异常;从TreeSet中取出元素第一个元素时,依然会引发ClassCastException异常。

2)采用compareTo(Object obj)方法比较对象时,都需要将被比较对象obj强制类型转换成相同类型,因为只有相同类的两个实例才能比较大小。即向TreeSet中添加的应该是同一个类的对象,否则会引发ClassCastException异常。

3)当把一个对象加入TreeSet集合中时,TreeSet调用该对象的compareTo(Object obj)方法与容器中的其他对象比较大小,然后根据红黑树算法决定它的存储位置,如果两个对象通过compareTo(Object obj)比较相等,TreeSet即认为它们存储同一位置。(如果对红黑树算法不是很了解可以去网上查询一下)

4)TreeSet集合判断两个对象不相等的标准:两个对象通过equals方法比较返回false,或通过compareTo(Object obj)比较没有返回0——即使两个对象时同一个对象,TreeSet也会把它们当成两个对象进行处理,具体代码如下:package com.yoodb;

import java.util.TreeSet;

class A implements Comparable {

int age;

public A(int age) {

this.age = age;

}

public boolean equals(Object obj) {

return false;

}

public int compareTo(Object obj) {

return 1;

}

}

public class TestTreeSet {

public static void main(String[] args) {

TreeSet set = new TreeSet();

A a1 = new A(21);

set.add(a1);

System.out.println(set.add(a1));

System.out.println(set);

((A) (set.first())).age = 25;

System.out.println(((A) (set.last())).age);

}

}

结果运行如下:true

[com.A@73cbc5cb, com.A@73cbc5cb]

25

1)把同一对象添加两次,a1对象的equals方法返回false,而且compareTo(Object obj)方法总是返回1,TreeSet会认为a1对象和它自己也不相同,因此TreeSet中添加两个a1对象。而TreeSet对象保存的两个元素实际上是同一个元素。所以当修改TreeSet集合里第一个元素的age属性后,该TreeSet集合里最后一个元素的age属性也随之改变了。

2)两个对象通过equals方法比较返回true,通过compareTo(Object obj)方法比较不返回0时TreeSet将会把这两个对象保存在不同位置,从而两个对象都可以添加成功;

3)两个对象通过equals方法比较返回false,通过compareTo(Object obj)方法比较返回0两个对象通过compareTo(Object obj)方法比较相等,TreeSet将试图把它们保存在同一个位置,但实际上又不行(否则将只剩下一个对象);

2、定制排序

实现定制排序需要在创建TreeSet集合对象时提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑。具体实现代码如下:package com.yoodb;

import java.util.Comparator;

import java.util.TreeSet;

class Age {

int age;

public Age(int age) {

this.age = age;

}

public String toString() {

return "age 对象 (age:" + age + ")";

}

}

public class TestTreeSet {

public static void main(String[] args) {

TreeSet ts = new TreeSet(new Comparator() {

public int compare(Object o1, Object o2) {

Age a1 = (Age) o1;

Age m2 = (Age) o2;

if (a1.age > m2.age) {

return -1;

} else if (a1.age == m2.age) {

return 0;

} else {

return 1;

}

}

});

ts.add(new Age(21));

ts.add(new Age(25));

ts.add(new Age(-9));

System.out.println(ts);

}

}

运行程序结果如下:[M 对象 (age:25), M 对象 (age:21), M 对象 (age:-9)]

创建一个Comparator接口的匿名内部类对象,负责ts集合的排序。当把Age对象添加到集合中时,无须Age类实现Comparable接口,此时TreeSet无须通过Age对象来比较大小,而是由与TreeSet关联的Comparator对象来负责集合元素的排序。使用定制排序时,TreeSet对集合元素排序时不管集合元素本身的大小,而是由Comparator对象负责集合元素的排序规则。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值