Java面向对象练习:Person类继承与排序

定义Person抽象类,Student类、Company类,Employee类。

Person类的属性 :String name, int age, boolean gender
Person类的方法:

复制代码
public Person(String name, int age, boolean gender);
public String toString();         //返回"name-age-gender"格式的字符串
public boolean equals(Object obj);//比较name、age、gender,都相同返回true,否则返回false

Student 类继承自Person,属性:String stuNo, String clazz
Student类的方法:

复制代码
//建议使用super复用Person类的相关有参构造函数
public Student(String name, int age, boolean gender, String stuNo, String clazz);
public String toString();         //返回 "Student:person的toString-stuNo-clazz"格式的字符串
public boolean equals(Object obj);//首先调用父类的equals方法,如果返回true,则继续比较stuNo与clazz。

Company 类属性:String name
Company类方法:

复制代码
public Company(String name);
public String toString();         //直接返回name
public boolean equals(Object obj);//name相同返回true

Employee 类继承自Person,属性:Company company, double salary
Employee类方法:

复制代码
//建议使用super复用Person类的相关有参构造函数
public Employee(String name, int age, boolean gender, double salary, Company company);
public String toString();         //返回"Employee:person的toString-company-salary"格式的字符串
public boolean equals(Object obj);//首先调用父类的equals方法,如果返回true。再比较company与salary。
//比较salary属性时,使用DecimalFormat df = new DecimalFormat("#.#");保留1位小数

编写equals方法重要说明:

  1. 对Employee的company属性的比较。要考虑传入为null的情况。如果company不为null且传入为null,返回false
  2. 对所有String字符类型比较时,也要考虑null情况。

提示

  1. 排序可使用Collections.sort
  2. equals方法要考虑周全

main方法说明

  1. 创建若干Student对象、Employee对象。
    输入s,然后依次输入name age gender stuNo clazz创建Student对象
    输入e,然后依次输入name age gender salary company创建Employee对象
    然后将创建好的对象放入List<Person> personList。输入其他字符,则结束创建。

创建说明: 对于String类型,如果为null则不创建对象,而赋值为null。对于company属性,如果为null则赋值为null,否则创建相应的Company对象。

  1. 对personList中的元素实现先按照姓名升序排序,姓名相同再按照年龄升序排序 。提示:可使用Comparable<Person>Comparator<Person>

  2. 接受输入,如果输入为exitreturn退出程序,否则继续下面步骤。

  3. 将personList中的元素按照类型分别放到stuList与empList。注意:不要将两个内容相同的对象放入列表(是否相同是根据equals返回结果进行判定)。

  4. 输出字符串stuList,然后输出stuList中的每个对象。

  5. 输出字符串empList,然后输出empList中的每个对象。

1-3为一个测试点
4-6为一个测试点

输入样例:

复制代码
s zhang 23 false 001 net15
e wang 18 true 3000.51 IBM
s zhang 23 false 001 net15
e bo 25 true 5000.51 IBM
e bo 25 true 5000.52 IBM
e bo 18 true 5000.54 IBM
e tan 25 true 5000.56 IBM
e tan 25 true 5000.51 IBM
s wang 17 false 002 null
s wang 17 false 002 null
e hua 16 false 1000 null
s wang 17 false 002 net16
e hua 16 false 1000 null
e hua 18 false 1234 MicroSoft
!
continue

输出样例:

复制代码
Employee:bo-18-true-IBM-5000.54
Employee:bo-25-true-IBM-5000.51
Employee:bo-25-true-IBM-5000.52
Employee:hua-16-false-null-1000.0
Employee:hua-16-false-null-1000.0
Employee:hua-18-false-MicroSoft-1234.0
Employee:tan-25-true-IBM-5000.56
Employee:tan-25-true-IBM-5000.51
Student:wang-17-false-002-null
Student:wang-17-false-002-null
Student:wang-17-false-002-net16
Employee:wang-18-true-IBM-3000.51
Student:zhang-23-false-001-net15
Student:zhang-23-false-001-net15
stuList
Student:wang-17-false-002-null
Student:wang-17-false-002-net16
Student:zhang-23-false-001-net15
empList
Employee:bo-18-true-IBM-5000.54
Employee:bo-25-true-IBM-5000.51
Employee:hua-16-false-null-1000.0
Employee:hua-18-false-MicroSoft-1234.0
Employee:tan-25-true-IBM-5000.56
Employee:tan-25-true-IBM-5000.51
Employee:wang-18-true-IBM-3000.51

代码如下:

java 复制代码
import java.text.DecimalFormat;
import java.util.*;

abstract class Person {
    String name;
    int age;
    boolean gender;
    public Person(String name, int age, boolean gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    @Override
    public String toString() {
        return name + "-" + age + "-" + gender;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && gender == person.gender && Objects.equals(name, person.name);
    }
}
class Student extends Person {
    private String stuNo;
    private String clazz;
    public Student(String name, int age, boolean gender, String stuNo, String clazz) {
        super(name, age, gender);
        this.stuNo = stuNo;
        this.clazz = clazz;
    }
    @Override
    public String toString() {
        String clazzStr = (clazz == null) ? "null" : clazz;
        return "Student:" + super.toString() + "-" + stuNo + "-" + clazzStr;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        Student student = (Student) o;
        return Objects.equals(stuNo, student.stuNo) && Objects.equals(clazz, student.clazz);
    }
}
class Company {
    private String name;

    public Company(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Company company = (Company) o;
        return Objects.equals(name, company.name);
    }
}
class Employee extends Person {
    private Company company;
    private double salary;
    public Employee(String name, int age, boolean gender, double salary, Company company) {
        super(name, age, gender);
        this.salary = salary;
        this.company = company;
    }
    @Override
    public String toString() {
        String salaryStr;
        if (salary == Math.floor(salary) && !Double.isInfinite(salary)) {
            salaryStr = String.format("%.1f", salary);
        } else {
            DecimalFormat df = new DecimalFormat("0.##########");
            salaryStr = df.format(salary);
        }
        String companyStr = (company == null) ? "null" : company.toString();
        return "Employee:" + super.toString() + "-" + companyStr + "-" + salaryStr;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        Employee employee = (Employee) o;
        if (company == null && employee.company != null) return false;
        if (company != null && !company.equals(employee.company)) return false;
        DecimalFormat df = new DecimalFormat("#.#");
        return df.format(salary).equals(df.format(employee.salary));
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        List<Person> personList = new ArrayList<>();
        while (sc.hasNext()) {
            String type = sc.next();
            if (type.equals("s")) {
                String name = getValueOrNull(sc.next());
                int age = sc.nextInt();
                boolean gender = Boolean.parseBoolean(sc.next());
                String stuNo = getValueOrNull(sc.next());
                String clazz = getValueOrNull(sc.next());
                personList.add(new Student(name, age, gender, stuNo, clazz));
                sc.nextLine();
            } else if (type.equals("e")) {
                String name = getValueOrNull(sc.next());
                int age = sc.nextInt();
                boolean gender = Boolean.parseBoolean(sc.next());
                double salary = sc.nextDouble();
                String companyName = getValueOrNull(sc.next());
                // 处理company为null的情况
                Company company = (companyName != null) ? new Company(companyName) : null;
                personList.add(new Employee(name, age, gender, salary, company));
                sc.nextLine();
            } else {
                break;
            }
        }
        Collections.sort(personList, new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                if (p1.name == null && p2.name == null) return 0;
                if (p1.name == null) return -1;
                if (p2.name == null) return 1;
                int nameCompare = p1.name.compareTo(p2.name);
                return nameCompare != 0 ? nameCompare : Integer.compare(p1.age, p2.age);
            }
        });
        for (Person p : personList) {
            System.out.println(p);
        }
        while (true) {
            if (!sc.hasNext()) break;
            String input = sc.next();
            if (input.equals("exit")) break;
            List<Student> stuList = new ArrayList<>();
            List<Employee> empList = new ArrayList<>();
            for (Person p : personList) {
                if (p instanceof Student) {
                    Student s = (Student) p;
                    if (!containsStudent(stuList, s)) stuList.add(s);
                } else if (p instanceof Employee) {
                    Employee e = (Employee) p;
                    if (!containsEmployee(empList, e)) empList.add(e);
                }
            }
            System.out.println("stuList");
            for (Student s : stuList) System.out.println(s);
            System.out.println("empList");
            for (Employee e : empList) System.out.println(e);
        }
        sc.close();
    }
    private static String getValueOrNull(String value) {
        return "null".equals(value) ? null : value;
    }
    private static boolean containsStudent(List<Student> list, Student s) {
        for (Student student : list) {
            if (student.equals(s)) return true;
        }
        return false;
    }
    private static boolean containsEmployee(List<Employee> list, Employee e) {
        for (Employee employee : list) {
            if (employee.equals(e)) return true;
        }
        return false;
    }
}

学习记录:

1、Java 泛型用法

List: 是 Java 集合框架中的一个接口(interface),定义了有序列表的通用操作规范(如 add()、get()、size() 等),但是不能直接创建实例(无法通过 new List<>() 生成对象),因为接口只定义规范而不包含具体实现逻辑。

要创建一个实际可用的列表集合,必须使用 List 接口的实现类,其中最常用的就是:
ArrayList: 基于动态数组实现,查询效率高。
**LinkedList:**基于双向链表实现,插入 / 删除效率高。

java 复制代码
List<String> list1 = new ArrayList<>();    // 正确
List<String> list2 = new LinkedList<>();   // 正确
List<String> list3 = new CopyOnWriteArrayList<>();  // 正确

2、工具类 DecimalFormat

用于格式化数字(尤其是小数)的工具类,能将数字按照指定的模式转换为字符串,常用于控制小数位数、千位分隔符、百分比显示等场景。

步骤:

1、创建 DecimalFormat 对象通过指定 "模式字符串" 创建格式化器,例如:

java 复制代码
DecimalFormat df = new DecimalFormat("模式字符串");

2、格式化数字使用 format() 方法将数字(double 或 long)转为字符串:

java 复制代码
double num = 1234.567;
String result = df.format(num); // 按模式格式化

示例:

java 复制代码
import java.text.DecimalFormat;

public class Main {
    public static void main(String[] args) {
        // 创建DecimalFormat对象,指定模式字符串
        DecimalFormat df = new DecimalFormat("#,###.00");
        
        // 要格式化的数字
        double num = 1234.567;
        
        // 使用format()方法进行格式化
        String result = df.format(num);
        
        // 输出结果
        System.out.println(result); // 输出: 1,234.57
    }
}
典型用法
  1. 控制小数位数

模式 #.##:最多保留 2 位小数,自动去掉末尾的 0:

java 复制代码
df = new DecimalFormat("#.##");
df.format(123.4);   // "123.4"(1位小数)
df.format(123.456); // "123.46"(四舍五入保留2位)
df.format(123.0);   // "123"(无小数部分)

模式 0.00:强制保留 2 位小数,位数不足补 0:

java 复制代码
df = new DecimalFormat("0.00");
df.format(123.4);   // "123.40"(补0凑2位)
df.format(123.0);   // "123.00"(强制显示2位)
2. 整数部分处理

模式 0000:强制显示 4 位整数,不足补 0:

java 复制代码
df = new DecimalFormat("0000");
df.format(12);      // "0012"(补0凑4位)
df.format(12345);   // "12345"(超过4位则全部显示)

模式 #,###:添加千位分隔符:

java 复制代码
df = new DecimalFormat("#,###");
df.format(1234567); // "1,234,567"
3. 特殊格式(百分比、科学计数法)

百分比:模式 #.##%:

java 复制代码
df = new DecimalFormat("#.##%");
df.format(0.1234);  // "12.34%"(0.1234×100=12.34)

科学计数法:模式 0.##E0:

java 复制代码
df = new DecimalFormat("0.##E0");
df.format(123456);  // "1.23E5"(1.23×10⁵)

注意:

1)四舍五入:DecimalFormat 会自动对小数部分进行四舍五入(如 123.456 用 #.## 格式化后为 123.46)。

2)null 处理:格式化 null 会抛出 NullPointerException,需提前判断。

核心模式符号
符号 含义 示例(数字:1234.567)
0 强制显示的数字位,位数不足时补 0(整数 / 小数部分都适用) 模式 0000.00 → 1234.57
# 可选的数字位,只显示有效数字,无意义的 0 会省略 模式 ####.# → 1234.6
. 小数点,用于分隔整数和小数部分 模式 #.# → 1234.6
, 千位分隔符,用于整数部分分组 模式 #,### → 1,234
% 百分比符号,会将数字乘以 100 后显示 模式 #% → 123457%(1234.567 × 100 = 123456.7)
E 科学计数法,用于表示大 / 小数字 模式 0.00E0 → 1.23E3
相关推荐
不会算法的小灰2 小时前
Spring Boot 实现邮件发送功能:整合 JavaMailSender 与 FreeMarker 模板
java·spring boot·后端
辞旧 lekkk3 小时前
【c++】初识STL和string类
开发语言·c++·学习·萌新
高洁013 小时前
【无标题】大模型-扩散模型(Diffusion Model)原理讲解(3)
人工智能·python·神经网络·pygame
数据知道3 小时前
Go基础:json文件处理详解(标准库`encoding/json`)
开发语言·后端·golang·json·go语言
come112343 小时前
从PHP到Spring Boot:思维的转变与入门实战 (指南二)
开发语言·spring boot·php
hqwest3 小时前
QT肝8天19--Windows程序部署
开发语言·qt·qt打包
come112343 小时前
深入理解 Java和Go语法和使用场景(指南十一)
java·开发语言·golang
爱和冰阔落3 小时前
【C++ STL栈和队列下】deque(双端队列) 优先级队列的模拟实现与仿函数的介绍
开发语言·数据结构·c++·算法·广度优先
少陵野小Tommy3 小时前
C语言验证哥德巴赫猜想
c语言·开发语言·学习·算法