定义
Comparable接口规定了那些实现了这个接口的对象的排序规则。这个排序规则一般定义为对象在自然界的排序规则(int型按1,2,3,4,5...),或者被定义为重写compareTo(相等返回0,小于返回负数,大于返回正数)方法所用的规则。
所有实现了这个接口的对象List(Array)可以通过Collections.sort(Arrays.sort)方法自动实现排序。
举个例子(String类实现了Comparable接口):
String [] nameArray = {"zhangsan","lisi","wangermazi","Bob","Jack","Sherry"};
List<String> nameList = Arrays.asList(nameArray);
System.out.println("排序前列表:"+nameList);
Collections.sort(nameList);
System.out.println("排序后列表:"+nameList);
输出结果:
排序前列表:[zhangsan, lisi, wangermazi, Bob, Jack, Sherry]
排序后列表:[Bob, Jack, Sherry, lisi, wangermazi, zhangsan]
****由上面这个例子可以看出对实现了Comparable接口的对象列表使用Collections.sort方法可以对列表进行排序。****
并且实现了这个接口的对象可以不指定comparator就作为键值在sorted map或sorted set中使用。
再举个例子:
Random rand = new Random();
String [] nameArray = {"zhangsan","lisi","wangermazi","Bob","Jack","Sherry"};
List<String> nameList = Arrays.asList(nameArray);
System.out.println("排序前列表:"+nameList);
SortedMap<String,Object> sortedMap = new TreeMap<>();//这里通过TreeMap默认的构造器,而没有指定Comparator对象
for(String str:nameList){
sortedMap.put(str,rand.nextInt(100));
}
System.out.println("Map添加元素后:"+sortedMap);
输出结果:
排序前列表:[zhangsan, lisi, wangermazi, Bob, Jack, Sherry]
添加元素后:{Bob=6, Jack=16, Sherry=61, lisi=83, wangermazi=17, zhangsan=0} //可以发现TreeMap已经按照String默认排序规则为我们排好序了
****由上面这个例子可以看出当某个类实现了Comparable接口时,使用SortedMap对象把这个类的对象作为键值存储数据时会根据它的自然排序规则进行排序。****
一个类C的自然排序在当且仅当对于所有的C的对象(譬如说e1,e2)都有e1.compareTo(e2)==0和e1.equals(e2)具有相同的返回值时被看作与equals一致。但必须注意的是null不是任何类的实例,compareTo(null)将会跑出一个异常。
****Java强烈推荐(但不是必须)自然排序的结果与equals的结果一致****。这是由于当我们在使用没有显式指定comparator的sorted对象时,如果这个类的自然排序与equals方法不一致就会出现很多问题。举个例子,当我们添加两个键(a和b,a.equals(b) == false并且a.compareTo(b) == 0)到一个SortedMap中, 如果我们未给SortedMap对象指定comparator对象,那么当我们添加完a后再添加b时,map的长度不会改变,因为此时系统根据compareTo的结果判定这两个对象是同一个对象。
根据上面这段话写个例子测试下:
1,定义Person类
public class Person implements Comparable{
private String name;
public Person(String name){
this.name = name;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
@Override
public int compareTo(Object obj){
if(this == obj){
return 0;
}
if(obj instanceof Person){
Person p = (Person)obj;
if(p.getName().equals(this.name)){
return 0;
}else{
return p.getName().compareTo(this.name);
}
}
return this.toString().compareTo(obj.toString());
}
}
2,编写测试类
public class Test{
public static void main(String [] args){
Person p1 = new Person("hha");
Person p2 = new Person("hha");
System.out.println(p1.equals(p2));
SortedMap<Person,Object> map = new TreeMap<>();
map.put(p1,1);
map.put(p2,2);
System.out.println(map);
}
}
输出结果:
false
{Person@7852e922=2}
可以看出我们添加了两个对象,最后Map中只有一个对象,这是因为在Person的compareTo方法中只要判定name相同的话对于SortedMap对象就代表两个对象相等,而Set接口的实现类不能存储相同的对象,所以这里实际只存储了一个对象。