您的位置:首页 > 其它

Comparator和Comparable之间的区别

2017-11-22 21:16 369 查看
简介
Comparable接口

Comparator接口

Comparator和Comparable的区别

栗子

简介

Comparable接口

该接口对每个实现它的类的对象强加了排序规则。该排序称之为自然排序(natural ordering)。方法
public int compareTo(T o)
是自然排序的排序方法。

实现了comparable接口类的
List或者arrays
对象可以通过调用以下方法进行排序:

1. Collections#sort(List<T> list) //内部是调用第二个方法进行排序
2.  Arrays#sort(Object[] a)       //算法是合并排序或二分排序 n^2算法复杂度

//此外,可以通过将元素添加到一下集合或Map中实现排序
3. SortedMap tm = new TreeMap();
4. SortedSet ts = new TreeSet();


自然排序中,
e1.compareTo(e2) == 0
的布尔值应该等价于
e1.equals(e2)
。注意
null
不属于任何类的实例,故
e.compareTo(null)
应抛出空指针异常,尽管此时
e.equals(null)
false


实际上,所有实现comparable的类中方法
compareTo
equals
方法值是等价的。一个特例就是
java.math.BigDecimal


Comparator接口

通过比较两个入参得到顺序。返回值有三种:

1,入参一大于入参二。

0,入参相同。

-1,入参一小于入参二。

实现的类必须保证以下 要求:

sgn(compare(x, y)) == -sgn(compare(y, x))
。暗示着
compare(x, y)
抛异常,则
compare(y,x)
也抛异常。

((compare(x, y) < 0),((compare(y,z) < 0)
暗示着
((compare(x,z) < 0)


compare(x, y)==0
暗示着
sgn(compare(x, z))==sgn(compare(y, z))


通常情况下,实现Comparator的类并不被严格要求要遵循
(compare(x, y)==0) == (x.equals(y))
,但是违反该条件的应该明确地指出这一事实,即说明条件
(compare(x, y)==0) == (x.equals(y))
并不成立。

实现Comparator的接口的
List或者arrays
对象可以通过调用以下方法进行排序:

1. Collections#sort(List<T> list,, Comparator<? super T> c) //内部是调用第二个方法进行排序
2.  Arrays#sort(Object[] a, Comparator<? super T> c)       //算法是合并排序或二分排序 n^2算法复杂度

//此外还可以通过将对象加入以下集合或Map实现排序
3. SortedMap tm = new TreeMap(Comparator<? super K> comparator);
4. SortedSet ts = new TreeSet(Comparator<? super K> comparator);


如果有多个比较规则,可以充分利用
Comparator
接口的默认方法:

default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}


Comparator和Comparable的区别

参数ComparableComparator
排序逻辑排序逻辑必须在待排序对象的类中,故称之为自然排序排序逻辑在另一个实现
实现实现Comparable接口实现Comparator接口
排序方法
int compareTo(Object o1)
int compare(Object o1,Object o2)
触发排序Collections.sort(List)Collections.sort(List, Comparator)
接口所在包
java.lang.Comparable
java.util.Comparator

栗子

假设我们想要人类先以姓名升序排序,假如姓名一样则按照年龄排序,则代码可以如下:

Person.java


@Data
@NoArgsConstructor
@AllArgsConstructor
/**
* @author hjb
*/
public class Person  implements Comparable {
private String name;
private Integer age;
private String mind;
@Override
public int compareTo(Object o) {
Person targetPerson = (Person)o;
int ret = this.name.compareTo(targetPerson.getName());
if(ret == 0){
return Integer.compare(this.age,targetPerson.getAge());
}
if(ret == 0){
return this.getMind().compareTo(targetPerson.getMind());
}
return ret;
}
}


PersonComparator.java


public class PersonComparator implements Comparator<Person> {
@Override
public int compare(Person p, Person p2) {

int ret = p.getName().compareTo(p2.getName());
if(ret == 0){
return p.getAge().compareTo(p2.getAge());
}
return ret;
}
}


PersonComparator2.java


public class PersonComparator2 implements Comparator<Person> {
@Override
public int compare(Person p, Person p2) {
return p.getMind().compareTo(p2.getMind());
}
}


TestCompare.java


public class TestComparable {

public static void main(String[] args){
//取数据
List<Person> personList = generatePersonList();
//排序一: 正常
Collections.sort(personList);
print("Collections.sort(list)",personList);
//排序二:发现正常了
PersonComparator pc = new PersonComparator();
PersonComparator2 pc2 = new PersonComparator2();

bdfa
Collections.sort(personList,pc.thenComparing(pc2));
print("thenComparing",personList);
//排序三:正常
SortedSet<Person> ts = new TreeSet<>(personList);
print("TreeSet",ts);
//排序四:发现某个Person实例被吃掉了,因为TreeSet认为CompareTo为0,则两个Person实例相同
SortedSet<Person> ts2 = new TreeSet<>(new PersonComparator());
ts2.addAll(personList);
print("TreeSet(Comparator)",ts2);
}

//生成待排序数组
private static List<Person> generatePersonList() {
List<Person> retList = new ArrayList<>(16);
retList.addAll(
Arrays.asList(
new Person[]{
new Person("erMaZi", 19, "good"),
new Person("liSi", 17, "bad"),
new Person("wangWu", 18, "middle"),
new Person("wangWu", 18, "middla"),
}
)
);
return retList;
}
public static void print(String message,List<Person> personList){
System.out.println(message+":");
for(Person p:personList){
System.out.println(p);
}
System.out.println();
}
public static void print(String message,SortedSet<Person> sortedSet){
System.out.println(message+":");
for(Person p:sortedSet){
System.out.println(p);
}
System.out.println();
}
}


Output


Collections.sort(list):
Person(name=erMaZi, age=19, mind=good)
Person(name=liSi, age=17, mind=bad)
Person(name=wangWu, age=18, mind=middla)
Person(name=wangWu, age=18, mind=middle)

thenComparing:
Person(name=erMaZi, age=19, mind=good)
Person(name=liSi, age=17, mind=bad)
Person(name=wangWu, age=18, mind=middla)
Person(name=wangWu, age=18, mind=middle)

TreeSet:
Person(name=erMaZi, age=19, mind=good)
Person(name=liSi, age=17, mind=bad)
Person(name=wangWu, age=18, mind=middla)
Person(name=wangWu, age=18, mind=middle)

TreeSet(Comparator):
Person(name=erMaZi, age=19, mind=good)
Person(name=liSi, age=17, mind=bad)
Person(name=wangWu, age=18, mind=middla)


参考资料
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息