Comparable and Comparator
前言
针对于Comparable和Comparator的区别:
- 对于Comparable 而言,该接口是个排序的接口。“对实现它的每个类的对象强加一个整体排序。 这个排序被称为类的自然排序 ,类的
compareTo
方法被称为其自然比较方法 。” 也就是说comparable的作用是相当于实体类本身添加排序功能。注意需要对于compareTo(Object o)方法进行重写操作。- Comparator :“比较功能,对一些对象的集合施加了一个整体排序 。 可以将比较器传递给排序方法(如
Collections.sort
或Arrays.sort
),以便对排序顺序进行精确控制。”也就是说如果该类没有通过实现Comparable接口,那么我们能够建立一个该类的比较器来进行排序的操作。需要注意的是一定要实现重写的compare(T t1,T t2)方法。
Comparable接口
Comparable简介
public interface Comparable<T>{ // 注意此处的泛型的导入数据的类型 public int compareTo(T o); }
- 该接口实现它的每个类的对象嘉庆一个整体的排序,它的这个排序称之为类的自然排序,类的compareTo方法被称为自然的比较方法。该接口中只有一个方法,就是compareTo().
- Comparable是java.lang包下面的接口,lang包下面可以看做是java的基础语言接口
代码实现检验
Person类
public class Person implements Comparable<Person>{
// 注意此处的泛型的操作
private Integer id;
private String name;
private Integer age;
public Person() {
}
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Person o) {
//return this.age - o.age;
return age - o.age;
}
}
public class DemoTest {
@Test
public void test(){
/*
* 对于Comparable的使用经常使用在set集合中,因为set集合中不重复的特性,
* TreeSet存储的元素是平衡二叉树的存储结构,所以使用的是有序的存储结构,故而需要
* 对应的类需要实现Comparable接口,进行排序的操作
*/
TreeSet<Person> set = new TreeSet<>();
set.add(new Person(1,"王五",33));
set.add(new Person(2,"张三",43));
set.add(new Person(3,"李四",23));
set.add(new Person(4,"周五",31));
//使用的是方法的引用的操作,将指定的集合进行输出的操作
set.forEach(System.out::println);
}
}
运行结果:
Person{id=3, name='李四', age=23}
Person{id=4, name='周五', age=31}
Person{id=1, name='王五', age=33}
Person{id=2, name='张三', age=43}
Comparator接口
Comparator简介
- Comparator表示的是比较接口,“比较功能,对一些对象的集合施加了一个整体排序 。 可以将比较器传递给排序方法(如
Collections.sort
或Arrays.sort
),以便对排序顺序进行精确控制。"- 实现接口,需要进行重写的方法是comparable(T t1,T t2)方法。
- 使用的是函数式接口,所以能够通过使用lambda表达式。
核心代码
@FunctionalInterface
interface Comparator<T>{
int compare(T t1,T t2);
}
代码实现检验
// 代码实现
Person类
public class Person {
String name;
int age;
String address;
public Person() {
}
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
检测实现类:
/**
* 比较器接口,参数是泛型,用户指定类型
*/
@FunctionalInterface
interface Comparator<T>{
/**
* 比较器接口的方法,参数是泛型类型,用户指定类型
*
* @param o1 用户在使用接口时约束的泛型对应具体数据类型
* @param o2 用户在使用接口时约束的泛型对应具体数据类型
* @return 如果返回0表示的是,两者相同,否则两者不同
*/
int compare(T o1,T o2);
}
/**
* @author 法外狂徒张三
* 2023/3/4
*/
public class Demo {
public static void main(String[] args) {
/**
* 数据的声明赋值部分
*/
Person[] arr = new Person[5];
for (int i = 0; i < arr.length; i++) {
int age = (int) (Math.random()*50);
arr[i] = new Person("小八嘎",age,"日本");
}
/**
* 匿名内部类比较实现
*/
comparatorArray(arr, (o1, o2) -> o1.getAge() - o2.getAge());
/**
* lambda分析,
* 首先方法:
* int compare(T o1,T o2);
* 获取泛型之后,泛型的类型是person类型
* 返回值的数据类型是int类型
*
* 方法的参数:2个参数
* 参数的类型都是Person类型
* 最终:
* (o1,o2) -> {所欲要的最重的返回值}
*/
comparatorArray(arr, (o1, o2) -> o1.getAge() - o2.getAge());
for (Person person : arr) {
System.out.println(person);
}
}
/**
* 使用的是排序的操作,排序的数组是person 类型,排序的规则使用自定义Comparator 接口实现
* 接口约束 person 类型
*
* @param arr Person类型的数据
* @param com 针对于Person类型数组的Comparator 比较器接口实现
*/
public static void comparatorArray(Person[] arr,Comparator<Person> com){
/**
* 采用的核心算法是选择排序的算法操作
*/
for (int i = 0; i < arr.length - 1; i++) {
int index = i;
/**
* 对于比较器中的泛型操作,目前约束的类型是 Person 类型
* 当前数组中存储的类型就是Person类型对象,可以作为参数,
* 同时利用compare 方法 返回值返回int类型的数据,作为
* 排序算法的规则限制。
*/
for (int j = i + 1; j < arr.length; j++) {
if (com.compare(arr[index],arr[j] ) > 0 ){
index = j;
}
}
if (index != i) {
Person temp = arr[index];
arr[index] = arr[i];
arr[i] = temp;
}
}
}
}
运行结果:
Person{name='小八嘎', age=13, address='日本'}
Person{name='小八嘎', age=18, address='日本'}
Person{name='小八嘎', age=33, address='日本'}
Person{name='小八嘎', age=38, address='日本'}
Person{name='小八嘎', age=45, address='日本'}
/*
* 进行检测,对于数据进行比较
*/
public class MyComparator {
public static void main(String[] args) {
Person[] arr = new Person[5];
for (int i = 0; i < arr.length; i++) {
int age = (int) (Math.random()*50);
arr[i] = new Person("小八嘎",age,"日本");
}
// 对于数据进行比较操作
Arrays.stream(arr).sorted((o1, o2) -> o1.getAge() - o2.getAge()).forEach(System.out::println);
}
}
运行结果:
Person{name='小八嘎', age=4, address='日本'}
Person{name='小八嘎', age=15, address='日本'}
Person{name='小八嘎', age=16, address='日本'}
Person{name='小八嘎', age=43, address='日本'}
Person{name='小八嘎', age=49, address='日本'}