jmu-Java-PTA题解 (5.2 - 面向对象进阶--02-接口-Comparator) 网安2312陈卓
问题要求
Arrays.sort可以对所有实现Comparable的对象进行排序。但如果有多种排序需求,如有时候需对name进行降序排序,有时候只需要对年龄进行排序。使用Comparable无法满足这样的需求。可以编写不同的Comparator来满足多样的排序需求。
-
编写PersonSortable2类
属性:private name(String)、private age(int)
有参构造函数:参数为name,age
toString方法:返回格式name-age -
编写Comparator类
- 编写NameComparator类,实现对name进行升序排序
- 编写AgeComparator类,对age进行升序排序
-
main方法中
1.输入n
2. 输入n行name age,并创建n个对象放入数组
3. 对数组按照name进行升序排序后输出。
4. 在3的基础上对数组按照age进行升序排序后输出。
5. 最后最后两行使用如下代码输出NameComparator与AgeComparator所实现的所有接口。
System.out.println(Arrays.toString(NameComparator.class.getInterfaces()));
System.out.println(Arrays.toString(AgeComparator.class.getInterfaces()));
输入样例:
5
zhang 15
zhang 12
wang 14
Wang 17
li 17
输出样例:
NameComparator:sort
Wang-17
li-17
wang-14
zhang-15
zhang-12
AgeComparator:sort
zhang-12
wang-14
zhang-15
Wang-17
li-17
//最后两行是标识信息
关键点
- 接口实现与排序需求:Comparator 接口的使用是关键。通过实现 Comparator 接口,分别创建 NameComparator 和 AgeComparator 类,来满足对 PersonSortable2 对象的不同排序需求。这使得在不修改对象类本身(PersonSortable2 类)的情况下,能够灵活地根据不同的属性进行排序,体现了接口的灵活性和扩展性。
- 对象类的设计:PersonSortable2 类的设计要合理,包含了需要排序的属性(name 和 age),并且提供了相应的访问方法(getName 和 getAge)以及便于输出的 toString 方法。有参构造函数方便了对象的初始化,为后续的排序操作提供了基础。
- compare 方法的实现:在 NameComparator 和 AgeComparator 的 compare 方法中,根据不同的属性(name 和 age)实现了具体的比较逻辑。对于 name 的比较,使用了 String 类的 compareTo 方法;对于 age 的比较,直接进行数值相减。正确的比较逻辑是实现准确排序的核心。
- 排序操作的调用:在 main 方法中,使用 Collections.sort 方法,并传入相应的 Comparator 实现类(NameComparator 或 AgeComparator)来对 ArrayList 中的 PersonSortable2 对象进行排序。这要求对 Collections 工具类的 sort 方法有正确的理解和使用,确保排序操作能够按照预期进行。
- 反射获取接口信息:通过反射机制,使用 class.getInterfaces() 方法获取 NameComparator 和 AgeComparator 类所实现的接口信息。这部分代码展示了 Java 反射的基本应用,能够在运行时获取类的接口信息,增加了代码的动态性和可扩展性。
解题步骤
第一步:编写 PersonSortable2 类
定义 PersonSortable2 类,包含私有属性 name 和 age,并提供有参构造函数用于初始化属性,同时实现 getName、getAge 方法用于获取属性值,以及重写 toString 方法以便按要求格式输出对象信息。
class PersonSortable2 {
private String name;
private int age;
// 有参构造函数
public PersonSortable2(String name, int age) {
this.name = name;
this.age = age;
}
// 获取name的方法
public String getName() {
return this.name;
}
// 获取age的方法
public int getAge() {
return this.age;
}
// 重写toString方法
public String toString() {
return name + "-" + age;
}
}
第二步:编写 Comparator 类
分别编写 NameComparator 类和 AgeComparator 类,都实现 Comparator 接口,并根据不同属性重写 compare 方法以实现升序排序。
class NameComparator implements Comparator<PersonSortable2> {
public int compare(PersonSortable2 e1, PersonSortable2 e2) {
int namecompare = e1.getName().compareTo(e2.getName());
if (namecompare != 0) {
return namecompare;
} else {
return 0;
}
}
}
class AgeComparator implements Comparator<PersonSortable2> {
public int compare(PersonSortable2 e1, PersonSortable2 e2) {
return e1.getAge() - e2.getAge();
}
}
第三步:编写 main 方法
在 main 方法中,首先通过 Scanner 从控制台读取输入的整数 n,然后通过循环读取 n 行 name 和 age 的数据,创建 n 个 PersonSortable2 对象并添加到 ArrayList 中。接着使用 Collections.sort 方法分别传入 NameComparator 和 AgeComparator 对数组进行排序,并按要求输出排序结果。最后通过反射获取并输出两个比较器类所实现的接口信息。
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
ArrayList<PersonSortable2> arr = new ArrayList<PersonSortable2>();
for (int i = 0; i < n; i++) {
String name = in.next();
int age = in.nextInt();
PersonSortable2 e = new PersonSortable2(name, age);
arr.add(e);
}
Collections.sort(arr, new NameComparator());
System.out.println("NameComparator:sort");
for (PersonSortable2 e : arr) {
System.out.println(e.toString());
}
Collections.sort(arr, new AgeComparator());
System.out.println("AgeComparator:sort");
for (PersonSortable2 e : arr) {
System.out.println(e.toString());
}
System.out.println(Arrays.toString(NameComparator.class.getInterfaces()));
System.out.println(Arrays.toString(AgeComparator.class.getInterfaces()));
}
}
整体流程图:

整体代码:
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
class PersonSortable2{
private String name;
private int age;
public void PersonSortable(String name, int age){
this.name = name;
this.age = age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public String toString(){
return name+"-"+age;
}
}
class NameComparator implements Comparator<PersonSortable2>{
public int compare(PersonSortable2 e1, PersonSortable2 e2){
int namecompare = e1.getName().compareTo(e2.getName());
if(namecompare!=0){
return namecompare;
}else{
return 0;
}
}
}
class AgeComparator implements Comparator<PersonSortable2>{
public int compare(PersonSortable2 e1, PersonSortable2 e2){
return e1.getAge()-e2.getAge();
}
}
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
ArrayList<PersonSortable2> arr = new ArrayList<PersonSortable2>();
for(int i=0; i<n; i++){
PersonSortable2 e = new PersonSortable2();
String name = in.next();
int age = in.nextInt();
e.PersonSortable(name,age);
arr.add(e);
}
Collections.sort(arr,new NameComparator());
System.out.println("NameComparator:sort");
for(PersonSortable2 e:arr){
System.out.println(e.toString());
}
Collections.sort(arr,new AgeComparator());
System.out.println("AgeComparator:sort");
for(PersonSortable2 e:arr){
System.out.println(e.toString());
}
System.out.println(Arrays.toString(NameComparator.class.getInterfaces()));
System.out.println(Arrays.toString(AgeComparator.class.getInterfaces()));
}
}
思考:在解决该问题的过程中,7运用 Comparator 接口体现了 Java 面向对象编程中接口的强大作用和灵活性。与 Comparable 接口相比,Comparator 接口提供了一种更灵活的排序方式。Comparable 接口将排序逻辑直接定义在类内部,这意味着一个类只能有一种默认的排序方式,并且如果需要修改排序逻辑,就必须修改类的源代码。而 Comparator 接口将排序逻辑与类本身分离,使得同一个类可以根据不同的需求实现多种排序策略 ,并且使用 Comparator 接口使得代码的扩展性更强。当项目需求发生变化,需要增加新的排序规则时,只需要创建一个新的 Comparator 实现类,而不需要修改原有的类代码。这种设计模式遵循了 “开闭原则”,即对扩展开放,对修改关闭,使得代码在面对需求变更时更加健壮和易于维护。此外,通过反射获取接口信息的操作展示了 Java 语言强大的自省能力。这种能力使得程序在运行时能够动态地获取类的信息,包括接口、方法、属性等,为程序的动态性和灵活性提供了支持。在实际开发中,反射机制可以用于各种场景,如依赖注入、动态代理等,极大地增强了程序的适应性和可扩展性。

浙公网安备 33010602011771号