1、Comparable
英 [ˈkɒmpərəbl] 美 [ˈkɑːmpərəbl]
可比较的;可比的;可比性;可比;可比较
2、Comparator
美 [kəmˈpɜrətər]
n.
比较器,比色器,比较电路,比长仪,场强计
3、 Cloneable
可复制的
一、Comparable 接口
比如说:对一个整型数组排序
public static void main(String[] args) {
int[] array = {15,20,89,4,10,47,36};
//排序前
System.out.println(Arrays.toString(array));
Arrays.sort(array);
//排序后
System.out.println(Arrays.toString(array));
}
但是这种排序都是比较简单的排序,是针对整型,浮点型…
如果是对一些复杂类型进行排序
比如说:对学生进行排序
学生有很多属性,名字,年龄,分数等等
class Student{
public String name;
public int age;
public double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
public class TestDome {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("张三", 18, 58.5);
students[1] = new Student("李四", 10, 90);
students[2] = new Student("王二", 50, 70.7);
//排序前
System.out.println(Arrays.toString(students));
Arrays.sort(students);
//排序后
System.out.println(Arrays.toString(students));
}
}
上面并没有告诉我们比较的规则,是指定根据什么来排序,是根据姓名,还是年龄,还是分数来进行排序,是升序还是降序???
这样应该怎样进行排序呢???
下面我们看一下sort的实现,是怎样实现的
就是让每个元素都去调用 Comparable。Comparable就是 数组按照某个规律去排序。
comparable 是一个接口,这个接口里面只有一个compareTo方法
所以我们在实现学生这个类的时候就要实现 comparable 接口,重写compareTo方法
compareTo 方法是用来比较数组,那就需要看比较 结果是大于0,还是等于0,再者小于0.
class Student implements Comparable<Student>{
public String name;
public int age;
public double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
//this,谁调用compareTo 谁就是这个this
//这个compareTo 方法就是根据学生的年龄进行比较
@Override
public int compareTo(Student o) {
// if(this.age > o.age){
// return 1;
// }else if(this.age == o.age){
// return 0;
// }else {
// return -1;
// }
return this.age - o.age;
}
}
那此时就可以将学生进行排序了,根据学生的年龄来排序
由上得知 Arrays.sort();默认排序规律是升序(从小到大),那么逆序怎么实现呢?(交换 this.age 与 o.age的位置就可以了)
自定义的数据类型,要进行大小的比较,一定要实现可以比较的接口Comparable
但是 Comparable 接口存在着缺陷: 如果我们要以学生的分数或者名字来排序,就需要重新 把 compareTo 方法的实现重写一遍,
public int compareTo(Student o) {
return (int)(this.score - o.score);
}
那么通过名字去排序,要怎么写。
调用String的compareTo方法来进行比较
public int compareTo(Student o) {
return o.name.compareTo(this.name);
}
二、Comparator - 比较器
class Student {
public String name;
public int age;
public double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
public class TestDome {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("张三", 18, 58.5);
students[1] = new Student("李四", 10, 90);
students[2] = new Student("王二", 50, 70.7);
//排序前
System.out.println(Arrays.toString(students));
Arrays.sort(students);
//排序后
System.out.println(Arrays.toString(students));
}
}
最开始的时候比较还是会出错
进入sort,你会发现有很多比较规则
现在 我们来创建一个类,该类实现了Comparator接口
Ctrl+左键 进入 Comparator 接口
输出原理,跟前面讲的,是一样的, 大于就返回一个非零数字,等于返回0,小于返回负数
class Student{
public String name;
public int age;
public double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
//根据年龄来比较的比较器
class ageComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
那该如何使用比较器呢???
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("张三", 18, 58.5);
students[1] = new Student("李四", 10, 90);
students[2] = new Student("王二", 50, 70.7);
//排序前
System.out.println(Arrays.toString(students));
AgeComparator ageComparator = new AgeComparator();
Arrays.sort(students,ageComparator);
//排序后
System.out.println(Arrays.toString(students));
}
进入sort方法
如果要根据分数来比较,那就创建一个根据分数来比较的比较器
class ScoreComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return (int)(o1.score - o2.score);
}
}
根据姓名来排序,那就创建一根据姓名来比较的比较器
class Name implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
关于比较器总的代码
class Student{
public String name;
public int age;
public double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
class AgeComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
class ScoreComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return (int)(o1.score - o2.score);
}
}
class NameComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
public class TestDome {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("张三", 18, 58.5);
students[1] = new Student("李四", 10, 90);
students[2] = new Student("王二", 50, 70.7);
//排序前
System.out.println(Arrays.toString(students));
// ScoreComparator scoreComparator = new ScoreComparator();
// Arrays.sort(students,scoreComparator);
// AgeComparator ageComparator = new AgeComparator();
// Arrays.sort(students,ageComparator);
NameComparator nameComparator = new NameComparator();
Arrays.sort(students,nameComparator);
//排序后
System.out.println(Arrays.toString(students));
}
}
三、Cloneable - 克隆
Java 中内置了一些很有用的接口, Clonable 就是其中之一.
Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”.
但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常.
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(" 正在吃饭!");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常.
Cloneable 接口为什么是空的???
一个空接口称为标志接口,表示接口就表示,如果一个类实现了这个和标志接口,那这个类就可以被克隆
这个接口本来就是空的,有些是用语法解释不了的,但是clone方法为什么还是会报错???
那就要在这个类里面重写clone方法
要克隆一个对象,那这个类就要实现Cloneable接口,并且这个类要重写clone方法
一个对象被克隆,那就产生了一个副本,和这个对象一样
class Person implements Cloneable{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(" 正在吃饭!");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test1 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person("张三", 18);
Person person2 = (Person)person1.clone();
System.out.println(person2);
}
}