0.实验准备
0.1一个标准类
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
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;
}
}
0.2一个测试类,创建TreeSet对象并存入几个person对象
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class test9 {
public static void main(String[] args) {
Person p1=new Person("cao",40);
Person p2=new Person("bei",30);
Person p3=new Person("yu",20);
Person p4=new Person("aei",20);
Set<Person> ps=new TreeSet<>();
ps.add(p1);
ps.add(p2);
ps.add(p3);
ps.add(p4);
for (Person p : ps) {
System.out.println(p);
}
}
}
0.3运行结果
Exception in thread "main" java.lang.ClassCastException:
class com.test9.Person cannot be cast to class java.lang.
Comparable (com.test9.Person is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
0.4原因分析
TreeSet集合存取顺序是不一致的,但取数据的时候有一定的规则,基本数据类型有默认规则,读者可以将存入数据换成整形去实验一下。但是存入自定义的整形数据类型时则报错Person cannot be cast to class java.lang.Comparable。
1.改进规则问题引入
那么我们就手动写一个规则进去。发现TreeSet有参构造且参数是一个接口,我们先采取匿名内部类的方式实现,发现只重写了一个方法。comparaTo方法 根据返回值排序。
Result<0放左边 result>0放右边 =0不存o.变量是已经存的,this.变量正在存的String也继承了自然排序TreeSet不依赖.equals方法。
注:里面的规则非本文章重点
Comparator<? super E> comparator
Set<Person> ps=new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
//o1为当前要存储的对象 o2集合中的对象
int result=o1.getAge()-o2.getAge();
result=result==0?o1.getName().compareTo(o2.getName()):result;
return result;
}
});
1.1引入
既然只重写了接口中的一个方法,那么就是说接口中只有一个抽象方法呗,那么lambda表达式当然也是管用的。
//lambda实现
Set<Person> ps=new TreeSet<>((o1,o2)->{
//o1为当前要存储的对象 o2集合中的对象
int result=o2.getAge()-o1.getAge();
result=result==0?o2.getName().compareTo(o1.getName()):result;
return result;
});
1.2我们现在看看Comparator接口的所有方法,这就很奇怪了,为什么有俩抽象方法呢?那我不是应该重写俩方法才对吗?
1.3这就要说起java的祖宗Object了,Object是所有java类的父类,定义了一些方法,其中就有equals方法,让我们来看一下。果然在哈,那为什么不用重写呢?因为父类已经有该方法且是具体的方法。
1.4举个栗子
定义Animal接口
//相当于比较器
public interface Animal {
void eat();
}
//假如这个是超类Object
public class Cat {
//假如这个就是equals
public void eat(){
System.out.println("喜欢吃鱼");
}
}
测试–不报错
public class Test extends Cat implements Animal {
}
class TTest {
public static void main(String[] args) {
Animal animal=new Test();
animal.eat();
}
}
//喜欢吃鱼
1.5总结
如果一个类既有继承又有实现。并且接口中的方法与父类接口中的方法相同,那么该类不用重写接口中的方法也可以。