8.3.3 TreeSet类 2.定制排序

8.3.3 TreeSet类 2.定制排序

自然排序默认是升序排列的

TreeSet的自然排序是根据集合元素的大小, TreeSet将它们以升序排列

定制排序

如果需要实现定制排序,例如以降序排列,则可以通过Comparator接口的帮助。该接口里包含一个int compare(T o1,T o2)方法:

Comparator接口的compare方法 描述
int compare(T o1, T o2) Compares its two arguments for order.

该方法用于比较o1o2的大小:

  • 如果该方法返回正整数,则表明o1大于o2;
  • 如果该方法返回0,则表明o1等于o2;
  • 如果该方法返回负整数,则表明o1小于o2;

如何实现定制排序

如果需要实现定制排序,则需要在创建TreeSet集合对象时,提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑
由于Comparator是一个函数式接口,因此可使用Lambda表达式来代替Comparator对象。

程序 TreeSet定制排序 使用Lambda表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.util.*;

class M
{
int age;
public M(int age)
{
this.age = age;
}
public String toString()
{
return "M[age:" + age + "]";
}
}
public class TreeSetTest4
{
public static void main(String[] args)
{
// 此处Lambda表达式的目标类型是Comparator
TreeSet ts = new TreeSet((o1 , o2) ->
{
M m1 = (M)o1;
M m2 = (M)o2;
// 根据M对象的age属性来决定大小,age越大,M对象反而越小
return m1.age > m2.age ? -1
: m1.age < m2.age ? 1 : 0;
});
ts.add(new M(5));
ts.add(new M(-3));
ts.add(new M(9));
System.out.println(ts);
}
}

上面程序中使用了目标类型为ComparatorLambda表达式,它负责ts集合的排序。所以当把M对象添加到ts集合中时,M类无须实现Comparable接口,因为此时TreeSet无须通过M对象本身来比较大小,而是由与TreeSet关联的Lambda表达式来负责集合元素的排序
运行程序,看到如下运行结果:

1
[M[age:9], M[age:5], M[age:-3]]

放入TreeSet中对象的类型要相同

当通过Comparator对象(或Lambda表达式)来实现TreeSet的定制排序时,依然不可以向TreeSet中添加类型不同的对象,否则会引发ClassCastException异常。

相等的元素不会再次添加到TreeSet中

使用定制排序时, TreeSet对集合元素排序不管集合元素本身的大小,而是由Comparator对象(或Lambda表达式)负责集合元素的排序规则。 此时,TreeSet判断两个集合元素相等的标准是:通过Comparator(或Lambda表达式)比较两个元素返回了0,这样TreeSet不会把第二个元素添加到集合中。