OOP第二阶段(五到十周)作业总结

发布时间 2023-04-30 13:18:23作者: Vousêtesunique

一、前言

在第二阶段作业中,三次训练集得分依次是70、100、67
训练集04和训练集05题目难度较为简单,训练集04主要的知识点涉及Java对数据的处理,判断是否有重复数据、对重复数据的去除、对数据的排序和对数据的计算,对正则表达式的运用,以及面向对象相关的知识,比如训练集04 7-5 考察对类的封装设计、训练集05 7-5 7-6 考察类与类之间聚合关系的设计
训练集06题目难度比较困难,题目刚发布,老师就在群里温馨提示:本次题目集只有一道题目,难度较大,预计代码行数:1000+,需用时:20h+,建议尽早开始,尽早完成。我也是在题目发布下来的第一时间打开,近3000字的题目描述,写的过程也十分坎坷(后面再细说),最后只得了67分。题目涉及的算法不难,主要还是考察了面向对象程序设计,设计类、类与类的关系、类的方法以及对类的引用。

二、设计与分析

OOP训练集05 7-5 日期问题面向对象设计(聚合一)
类图如下:

设计分析与心得:先设计好DateUtil类、Day类、Month类、Year类之间的关系,根据题目要求:Day类聚合DateUtil类、Month类聚合Day类、Year类聚合Month类,再编写各个类中相应的属性、类构造方法及类方法,比如在Month类中int类型的value属性用于处理月份信息,Year类型的year属性用于组合Year类处理数据,restMin方法将月份设置为1,restMax方法将月份设置为12,validate方法检验数据的合法性,monthIncrement方法将月份值加1,monthReduction方法将月份值减1。
由于此题是之前OOP训练集03 7-3定义日期类的迭代,于是乎编写的过程顺利,使用聚合的设计也让在求日期前n天和后n天容易,一遍通过了所有测试点。
OOP训练集03 7-3定义日期类相比较,都将类进行了封装处理,不同的是聚合一将Year、Month、Day的属性和方法分别做成了单独的类。提高了代码的可读性,更容易维护;使得系统更灵活、更容易扩展,而且成本较低;接近于日常生活和自然的思考方式,势必提高软件开发的效率和质量。

源码如下

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int year = 0;
        int month = 0;
        int day = 0;

        int choice = input.nextInt();

        if (choice == 1) { // test getNextNDays method
            int m = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            DateUtil date = new DateUtil(year, month, day);

            if (!date.validate()) {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }

            m = input.nextInt();

            if (m < 0) {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }
            System.out.println(date.getNextNDays(m).showDate());
        } else if (choice == 2) { // test getPreviousNDays method
            int n = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            DateUtil date = new DateUtil(year, month, day);

            if (!date.validate()) {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }

            n = input.nextInt();

            if (n < 0) {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }
            System.out.println(date.getPreviousNDays(n).showDate());
        } else if (choice == 3) { // test getDaysofDates method
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            int anotherYear = Integer.parseInt(input.next());
            int anotherMonth = Integer.parseInt(input.next());
            int anotherDay = Integer.parseInt(input.next());

            DateUtil fromDate = new DateUtil(year, month, day);
            DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);

            if (fromDate.validate() && toDate.validate()) {
                System.out.println(fromDate.getDaysofDates(toDate));
            } else {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }
        } else {
            System.out.println("Wrong Format");
            input.close();
            System.exit(0);
        }
        input.close();
    }
}

class Year {
    private int value;

    public Year() { // 默认构造方法
    }

    public Year(int yearValue) { // 带参构造方法
        this.value = yearValue;
    }

    public int getValue() { // value gettter
        return value;
    }

    public void setValue(int yearValue) { // value setter
        this.value = yearValue;
    }

    public boolean isLeapYear() { // 判断是否为闰年
        return (this.value % 4 == 0 && this.value % 100 != 0)
                || this.value % 400 == 0;
    }

    public boolean validate() { // 效验数据合法性
        return this.value <= 2050 && this.value >= 1900;
    }

    public void yearIncrement() { // year + 1
        this.value++;
    }

    public void yearReduction() { // year - 1
        this.value--;
    }
}

class Month {
    private int value;
    private Year year;

    public Month() { // 默认构造方法
    }

    public Month(int yearValue, int monthValue) { // 带参构造方法
        this.year = new Year(yearValue);
        this.value = monthValue;
    }

    public int getValue() { // value getter
        return value;
    }

    public void setValue(int monthValue) { // value setter
        this.value = monthValue;
    }

    public Year getYear() { // year getter
        return year;
    }

    public void setYear(Year year) { // year setter
        this.year = year;
    }

    public void resetMin() { // 月份复位(1)
        value = 1;
    }

    public void resetMax() { // 月份设置为12
        value = 12;
    }

    public boolean validate() { // 效验数据合法性
        return value >= 1 && value <= 12;
    }

    public void monthIncrement() { // month + 1
        this.value++;
        if (this.value > 12) { // 下一年
            this.resetMin();
            this.year.yearIncrement();
        }
    }

    public void monthReduction() { // month - 1
        this.value--;
        if (this.value < 1) { // 前一年
            this.resetMax();
            this.year.yearReduction();
        }
    }
}

class Day {
    private int value;
    private Month month;
    private int[] mon_maxnum = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    public Day() { // 默认构造方法
    }

    public Day(int yearValue, int monthValue, int dayValue) { // 带参构造方法
        this.month = new Month(yearValue, monthValue);
        this.value = dayValue;
    }

    public int getValue() { // value getter
        return value;
    }

    public void setValue(int dayValue) { // value setter
        this.value = dayValue;
    }

    public Month getMonth() { // month getter
        return month;
    }

    public void setMonth(Month month) { // month setter
        this.month = month;
    }

    public void resetMin() { // 日期复位(1)
        value = 1;
    }

    public int getMon_Maxnum(int n) {
        if (this.getMonth().getYear().isLeapYear()) {
            this.mon_maxnum[2] = 29; // 闰年2月有29天
        } else {
            this.mon_maxnum[2] = 28; // 平年2月有28天
        }
        return mon_maxnum[n];
    }

    public void resetMax() { // 日期改为月最大值
        if (this.getMonth().getYear().isLeapYear()) {
            this.mon_maxnum[2] = 29; // 闰年2月有29天
        } else {
            this.mon_maxnum[2] = 28; // 平年2月有28天
        }
        value = mon_maxnum[month.getValue()];
    }

    public boolean validate() { // 效验数据合法性
        if (this.getMonth().getYear().isLeapYear()) {
            this.mon_maxnum[2] = 29; // 闰年2月有29天
        } else {
            this.mon_maxnum[2] = 28; // 平年2月有28天
        }
        return value >= 1 && value <= mon_maxnum[month.getValue()];
    }

    public void dayIncrement() { // day + 1
        this.value++;
        if (this.getMonth().getYear().isLeapYear()) {
            this.mon_maxnum[2] = 29; // 闰年2月有29天
        } else {
            this.mon_maxnum[2] = 28; // 平年2月有28天
        }
        if (this.value > this.getMon_Maxnum(this.getMonth().getValue())) {
            this.getMonth().monthIncrement(); // 下一月
            this.resetMin();
        }
    }

    public void dayReduction() { // day - 1
        this.value--;
        if (this.getMonth().getYear().isLeapYear()) {
            this.mon_maxnum[2] = 29; // 闰年2月有29天
        } else {
            this.mon_maxnum[2] = 28; // 平年2月有28天
        }
        if (this.value < 1) {
            this.month.monthReduction(); // 前一月
            this.resetMax();
        }
    }
}

class DateUtil {
    private Day day;

    public DateUtil() { // 默认构造方法
    }

    public DateUtil(int yearValue, int monthValue, int dayValue) { // 带参构造方法
        this.day = new Day(yearValue, monthValue, dayValue);
    }

    public Day getDay() { // day getter
        return day;
    }

    public void setDay(Day day) { // day setter
        this.day = day;
    }

    public boolean validate() { // 效验数据合法性
        // return day.validate();
        return this.getDay().getMonth().getYear().validate() && this.getDay().getMonth().validate()
                && this.getDay().validate();
    }

    public boolean compareDates(DateUtil date) { // 比较两个日期的大小
        boolean flag = false;
        if (this.getDay().getMonth().getYear().getValue() > date.getDay().getMonth().getYear().getValue()) {
            flag = true; // 先比较年
        } else if (this.getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()
                && this.getDay().getMonth().getValue() > date.getDay().getMonth().getValue()) {
            flag = true; // 年相同比较月
        } else if (this.getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()
                && this.getDay().getMonth().getValue() == date.getDay().getMonth().getValue()
                && this.getDay().getValue() > date.getDay().getValue()) {
            flag = true; // 年、月相同比较天
        }

        return flag;
    }

    public boolean equalTwoDates(DateUtil date) { // 判定两个日期是否相等
        return this.getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()
                && this.getDay().getMonth().getValue() == date.getDay().getMonth().getValue()
                && this.getDay().getValue() == date.getDay().getValue();
    }

    public String showDate() { // 日期值格式化
        return this.getDay().getMonth().getYear().getValue() + "-" + this.getDay().getMonth().getValue() + "-"
                + this.getDay().getValue();
    }

    public DateUtil getNextNDays(int n) { // 求下 n 天
        while (n-- > 0) {
            this.getDay().dayIncrement(); // 下一天
        }
        return this;
    }

    public DateUtil getPreviousNDays(int n) { // 求前 n 天
        while (n-- > 0) {
            this.getDay().dayReduction(); // 前一天
        }
        return this;
    }

    public int getDaysofDates(DateUtil date) { // 求两个日期之间的天数
        int sum = 0;
        while (this.equalTwoDates(date) == false) {
            sum++;
            if (this.compareDates(date)) {
                this.getDay().dayReduction();
            } else {
                date.getDay().dayReduction();
            }
        }
        return sum;
    }
}

OOP训练集05 7-5 日期问题面向对象设计(聚合二)
类图如下:

设计分析与心得:本题与上一题相似,只是改变了聚合关系:Year类聚合DateUtil类、Month类聚合DateUtil类、Day类聚合DateUtil类,类中的方法也相应改变了一些,但是算法不变。
只是没仔细看题,没发现两题的输出格式和日期限制不同,错了一次(说明要仔细看题哈),改完后就对了


源码如下:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int year = 0;
        int month = 0;
        int day = 0;

        int choice = input.nextInt();

        if (choice == 1) { // test getNextNDays method
            int m = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            DateUtil date = new DateUtil(year, month, day);

            if (!date.checkInputValidate()) {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }

            m = input.nextInt();

            if (m < 0) {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }
            System.out.print(date.showDate() + " next " + m + " days is:");
            System.out.println(date.getNextNDays(m).showDate());
        } else if (choice == 2) { // test getPreviousNDays method
            int n = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            DateUtil date = new DateUtil(year, month, day);

            if (!date.checkInputValidate()) {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }

            n = input.nextInt();

            if (n < 0) {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }
            System.out.print(date.showDate() + " previous " + n + " days is:");
            System.out.println(date.getPreviousNDays(n).showDate());
        } else if (choice == 3) { // test getDaysofDates method
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            int anotherYear = Integer.parseInt(input.next());
            int anotherMonth = Integer.parseInt(input.next());
            int anotherDay = Integer.parseInt(input.next());

            DateUtil fromDate = new DateUtil(year, month, day);
            DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);

            if (fromDate.checkInputValidate() && toDate.checkInputValidate()) {
                System.out.println("The days between " + fromDate.showDate() +
                        " and " + toDate.showDate() + " are:"
                        + fromDate.getDaysofDates(toDate));
            } else {
                System.out.println("Wrong Format");
                input.close();
                System.exit(0);
            }
        } else {
            System.out.println("Wrong Format");
            input.close();
            System.exit(0);
        }
        input.close();
    }
}

class Year {
    private int value;

    public Year() { // 默认构造方法
    }

    public Year(int yearValue) { // 带参构造方法
        this.value = yearValue;
    }

    public int getValue() { // value gettter
        return value;
    }

    public void setValue(int yearValue) { // value setter
        this.value = yearValue;
    }

    public boolean isLeapYear() { // 判断是否为闰年
        return (this.value % 4 == 0 && this.value % 100 != 0)
                || this.value % 400 == 0;
    }

    public boolean validate() { // 效验数据合法性
        return this.value <= 2020 && this.value >= 1820;
    }

    public void yearIncrement() { // year + 1
        this.value++;
    }

    public void yearReduction() { // year - 1
        this.value--;
    }
}

class Month {
    private int value;

    public Month() { // 默认构造方法
    }

    public Month(int monthValue) { // 带参构造方法
        this.value = monthValue;
    }

    public int getValue() { // value getter
        return value;
    }

    public void setValue(int monthValue) { // value setter
        this.value = monthValue;
    }

    public void resetMin() { // 月份复位(1)
        value = 1;
    }

    public void resetMax() { // 月份设置为12
        value = 12;
    }

    public boolean validate() { // 效验数据合法性
        return value >= 1 && value <= 12;
    }

    public void monthIncrement() { // month + 1
        this.value++;
    }

    public void monthReduction() { // month - 1
        this.value--;
    }
}

class Day {
    private int value;

    public Day() { // 默认构造方法
    }

    public Day(int dayValue) { // 带参构造方法
        this.value = dayValue;
    }

    public int getValue() { // value getter
        return value;
    }

    public void setValue(int dayValue) { // value setter
        this.value = dayValue;
    }

    public void dayIncrement() { // day + 1
        this.value++;
    }

    public void dayReduction() { // day - 1
        this.value--;
    }
}

class DateUtil {
    private Year year;
    private Month month;
    private Day day;
    private int[] mon_maxnum = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    public DateUtil() { // 默认构造方法
    }

    public DateUtil(int yearValue, int monthValue, int dayValue) { // 带参构造方法
        this.year = new Year(yearValue);
        this.month = new Month(monthValue);
        this.day = new Day(dayValue);
    }

    public Year getYear() { // year getter
        return year;
    }

    public void setYear(Year year) { // year setter
        this.year = year;
    }

    public Month getMonth() { // month getter
        return month;
    }

    public void setMonth(Month month) { // month setter
        this.month = month;
    }

    public Day getDay() { // day getter
        return day;
    }

    public void setDay(Day day) { // day setter
        this.day = day;
    }

    public void setDayMin() { // 设置日期最小值(1)
        this.getDay().setValue(1);
    }

    public void setDayMax() { // 设置日期最大值(当月最大天数)
        if (this.getYear().isLeapYear()) {
            this.mon_maxnum[2] = 29; // 闰年2月有29天
        } else {
            this.mon_maxnum[2] = 28; // 平年2月有28天
        }
        this.getDay().setValue(this.mon_maxnum[this.getMonth().getValue()]);
    }

    public boolean checkInputValidate() { // 效验数据合法性
        if (this.getYear().isLeapYear()) {
            this.mon_maxnum[2] = 29; // 闰年2月有29天
        } else {
            this.mon_maxnum[2] = 28; // 平年2月有28天
        }
        return this.getYear().validate() &&
                this.getMonth().validate() &&
                this.getMonth().getValue() >= 1 &&
                this.getMonth().getValue() <= this.mon_maxnum[this.getMonth().getValue()];
    }

    public DateUtil getNextNDays(int n) { // 求下 n 天
        while (n-- > 0) {
            if (this.getYear().isLeapYear()) {
                this.mon_maxnum[2] = 29; // 闰年2月有29天
            } else {
                this.mon_maxnum[2] = 28; // 平年2月有28天
            }
            this.getDay().dayIncrement(); // 下一天
            if (this.getDay().getValue() > this.mon_maxnum[this.getMonth().getValue()]) {
                this.getMonth().monthIncrement(); // 下一月
                if (this.getMonth().getValue() > 12) {
                    this.getYear().yearIncrement(); // 下一年
                    this.getMonth().resetMin();
                }
                this.setDayMin();
            }
        }
        return this;
    }

    public DateUtil getPreviousNDays(int n) { // 求前 n 天
        while (n-- > 0) {
            if (this.getYear().isLeapYear()) {
                this.mon_maxnum[2] = 29; // 闰年2月有29天
            } else {
                this.mon_maxnum[2] = 28; // 平年2月有28天
            }
            this.getDay().dayReduction(); // 前一天
            if (this.getDay().getValue() < 1) {
                this.getMonth().monthReduction(); // 前一月
                if (this.getMonth().getValue() < 1) {
                    this.getYear().yearReduction(); // 前一年
                    this.getMonth().resetMax();
                }
                this.setDayMax();
            }
        }
        return this;
    }

    public boolean compareDates(DateUtil date) { // 判定两个日期的先后
        boolean flag = false;
        if (this.year.getValue() > date.year.getValue()) {
            flag = true; // 先比较年
        } else if (this.getYear().getValue() == date.getYear().getValue()
                && this.getMonth().getValue() > date.getMonth().getValue()) {
            flag = true; // 年相同比较月
        } else if (this.getYear().getValue() == date.getYear().getValue()
                && this.getMonth().getValue() == date.getMonth().getValue()
                && this.getDay().getValue() > date.getDay().getValue()) {
            flag = true; // 年、月相同比较天
        }
        return flag;
    }

    public boolean equalTwoDates(DateUtil date) { // 判定两个日期是否相等
        return this.getYear().getValue() == date.getYear().getValue()
                && this.getMonth().getValue() == date.getMonth().getValue()
                && this.getDay().getValue() == date.getDay().getValue();
    }

    public String showDate() { // 日期值格式化
        return this.getYear().getValue() + "-"
                + this.getMonth().getValue() + "-"
                + this.getDay().getValue();
    }

    public int getDaysofDates(DateUtil date) { // 求两个日期之间的天数
        int sum = 0;
        while (this.equalTwoDates(date) == false) { // 直到两个日期相同时
            sum++;
            if (this.compareDates(date)) {
                if (this.getYear().isLeapYear()) {
                    this.mon_maxnum[2] = 29; // 闰年2月有29天
                } else {
                    this.mon_maxnum[2] = 28; // 平年2月有28天
                }
                this.getDay().dayReduction(); // 前一天
                if (this.getDay().getValue() < 1) {
                    this.getMonth().monthReduction(); // 前一月
                    if (this.getMonth().getValue() < 1) {
                        this.getYear().yearReduction(); // 前一年
                        this.getMonth().resetMax();
                    }
                    this.setDayMax();
                }
            } else {
                if (date.getYear().isLeapYear()) {
                    date.mon_maxnum[2] = 29; // 闰年2月有29天
                } else {
                    date.mon_maxnum[2] = 28; // 平年2月有28天
                }
                date.getDay().dayReduction(); // 前一天
                if (date.getDay().getValue() < 1) {
                    date.getMonth().monthReduction(); // 前一月
                    if (date.getMonth().getValue() < 1) {
                        date.getYear().yearReduction(); // 前一年
                        date.getMonth().resetMax();
                    }
                    date.setDayMax();
                }
            }
        }
        return sum;
    }
}

聚合一与聚合二的比较:
聚合一与聚合二大致相同,使用了类的聚合关系,区别就在于聚合一Day类聚合DateUtil类、Month类聚合Day类、Year类聚合Month类,而聚合二Year类聚合DateUtil类、Month类聚合DateUtil类、Day类聚合DateUtil类,聚合二的耦合性更低。
聚合一:

聚合二:

可以看出聚合二的复杂程度比聚合一更低。
通过观察两个类图可以看出:聚合一各类之间的关联程度更强,层层聚合,如果一个类存在问题,将导致整个程序出现问题,耦合性较高,而聚合二各类之间的关联程度更低,Year类、Month类、Day类聚合DateUtil类,即使一个类出现了问题,其余类的功能也能实现,耦合性较低。迪米特法则告诉我们应该尽可能地减少对象之间的依赖关系,以便更轻松地维护代码,所以在以后的面向对象设计中,聚合二的设计更好。
OOP训练集04 7-1 菜单计价程序-3 & OOP训练集06 7-1 菜单计价程序-4
类图如下:

设计分析与心得
“20+h 1000+行代码”,群消息温馨提示让我感到事情不简单,打开PTA,只有一题,怎么只有一题?20+h?1000+行代码?打开题目,3000字的描述,17个异常情况。虽然描述多,但也复杂。
先看题目描述吧,1h左右,大概看懂了题,再将题目有的四个类,Dish类、Meun类、Record类、Order类,的各类属性和方法初步编写完成。第一天就到这了。
之后就开始Main类的编写,第一到困难就将这6种情况(普通菜、特色菜、桌号标识、点菜、删除点菜、代点菜)分开,好在练习过正则表达式,就很容易地将这6种情况分开了。
然后逐一编写这6种情况,Main类越来越多,而且桌号标识需要储存和判断,加个Table类,用于储存桌号标识信息并判断信息是否合法,加个Table类还不够,再加了个Tables类,保存所有桌号标识信息并能查找桌号标识信息、判断数据是否合法、添加桌号标识信息,类似Dish类与Meun类的关系。
也完善了类中的方法,异常情况比较多,对数据进行了很多判断处理,比如

菜名要存在,否则 dishName does not exist;
点菜的订单序号必须从小到大,否则 record serial number sequence error;
普通菜份额是1、2、3,特价菜份额是1、2,否则 portion out of range;
份数不能超过15,否则 num out of range。
菜名不存在、份额超出范围、份数超出范围,按记录中从左到右的次序优先级由高到低,输出时只提示优先级最高的那个错误。
写到这,只过了4天,感觉好像快写完了,而且还有3天,很开心。NO!第一次提交就是0分,而且很多是格式错误,修改好格式后,40+分。
不久,又发现了一个很大的问题,代点菜是别的桌点菜,但是订单信息需要打印在被点菜的那桌上,那这样的话,就不能每次输入,程序就打印一个信息。我的解决方法就是:储存语句。

在Order类中添加一个String型的数组,用于储存订单信息,再最后逐一将各个订单信息按顺序输出。

修修改改,改改修修,最终只得了67分。好消息就是嘛,及格了,嗯。

后来才知道,代点菜的那桌的订单信息,要加一句“订单序号 table 代点菜桌号 pay for table 被代点菜桌号 价格”,题目要求里没说,应该在菜单计价系列的别的题中有提及。
源码如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Menu menu = new Menu();
        Tables tables = new Tables();
        int tableCount = 0;
        boolean isTableError = false;
        while (true) {
            String str = sc.nextLine();
            if (str.equals("end")) {
                break;
            }
            String[] splitStr = str.split(" ");
            if (splitStr.length == 2 && splitStr[1].matches("[0-9]+")) { // 菜普中普通菜
                if (tableCount != 0) {
                    tables.findTableByInedx(tableCount - 1).order.addSentence("invalid dish");
                } else {
                    int unit_price = Integer.parseInt(splitStr[1]);
                    menu.addDish(splitStr[0], unit_price, false);
                }
            } else if (splitStr.length == 3 && splitStr[1].matches("[0-9]+")
                    && splitStr[2].equals("T")) { // 菜谱中特色菜
                if (tableCount != 0) {
                    tables.findTableByInedx(tableCount - 1).order.addSentence("invalid dish");
                } else {
                    int unit_price = Integer.parseInt(splitStr[1]);
                    menu.addDish(splitStr[0], unit_price, true);
                }
            } else if (splitStr.length == 4 && splitStr[0].equals("table")) { // 桌子
                if (splitStr[1].matches("[0-9]+")
                        && splitStr[2].matches("\\d{4}/\\d{1,2}/\\d{1,2}")
                        && splitStr[3].matches("\\d{1,2}/\\d{1,2}/\\d{1,2}")) {
                    int tableNum = Integer.parseInt(splitStr[1]);
                    String[] dates = splitStr[2].split("/");
                    String[] times = splitStr[3].split("/");
                    int year = Integer.parseInt(dates[0]);
                    int month = Integer.parseInt(dates[1]);
                    int day = Integer.parseInt(dates[2]);
                    int hour = Integer.parseInt(times[0]);
                    int minute = Integer.parseInt(times[1]);
                    int second = Integer.parseInt(times[2]);
                    int dayOfWeek = getDayOfWeek(splitStr[2]);
                    Table newTable = tables.addTable(tableNum, year, month, day, hour, minute, second, dayOfWeek);
                    if (newTable != null) {
                        isTableError = false;
                        tableCount++;
                    } else {
                        isTableError = true;
                    }
                } else {
                    isTableError = true;
                    if (tableCount == 0) {
                        System.out.println("wrong format");
                    } else {
                        if (tableCount != 0) {
                            tables.findTableByInedx(tableCount - 1).order.addSentence("wrong format");
                        } else {
                            System.out.println("wrong format");
                        }
                    }
                }
            } else if (splitStr.length == 4 && splitStr[0].matches("[0-9]+")
                    && splitStr[2].matches("[0-9]+")
                    && splitStr[3].matches("[0-9]+")) { // 点菜
                if (isTableError == false && tableCount > 0) {
                    int orderNum = Integer.parseInt(splitStr[0]);
                    int portion = Integer.parseInt(splitStr[2]);
                    int num = Integer.parseInt(splitStr[3]);
                    tables.findTableByInedx(tableCount - 1).order.addARecord(orderNum, splitStr[1], portion, num, menu,
                            true);
                }
            } else if (splitStr.length == 2
                    && splitStr[1].equals("delete")
                    && splitStr[0].matches("[0-9]+")) { // 删除
                if (isTableError == false && tableCount > 0) {
                    int orderNum = Integer.parseInt(splitStr[0]);
                    tables.findTableByInedx(tableCount - 1).order.delARecordByOrderNum(orderNum);
                }
            } else if (splitStr.length == 5 && splitStr[0].matches("[0-9]+")
                    && splitStr[1].matches("[0-9]+")
                    && splitStr[3].matches("[0-9]+")
                    && splitStr[4].matches("[0-9]+")) { // 代点菜
                if (isTableError == false && tableCount > 0) {
                    int tableNum = Integer.parseInt(splitStr[0]);
                    int orderNum = Integer.parseInt(splitStr[1]);
                    int portion = Integer.parseInt(splitStr[3]);
                    int num = Integer.parseInt(splitStr[4]);
                    if (tables.findTableByNum(tableNum) != null) {
                        tables.findTableByInedx(tableCount - 1).order.addARecord(orderNum, splitStr[2], portion, num,
                                menu, false);
                        String addSentenceString = orderNum + " table "
                                + tables.findTableByInedx(tableCount - 1).tableNum + " pay for table " + tableNum + " "
                                + tables.findTableByInedx(tableCount - 1).order.findRecordByNum(orderNum).getPrice();
                        tables.findTableByNum(tableCount - 1).order.addSentence(addSentenceString);
                    } else {
                        if (tableCount != 0) {
                            tables.findTableByInedx(tableCount - 1).order
                                    .addSentence("Table number : " + tableNum + " does not exist");
                        } else {
                            System.out.println("Table number : " + tableNum + " does not exist");
                        }
                    }
                }
            } else {
                if (isTableError == false && tableCount == 0) {
                    System.out.println("wrong format");
                }
                if (tableCount > 0) {
                    tables.findTableByInedx(tableCount - 1).order.addSentence("wrong format");
                }
            }
        }
        tables.showTables();
        sc.close();
    }

    public static int getDayOfWeek(String date) { // 找星期几
        String[] arr = { "0", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
        Date dateUtil = new Date();
        SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd");
        try {
            dateUtil = f.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        int index = 0;
        String temp = dateUtil.toString();
        String[] temp1 = temp.split(" ");
        for (int i = 0; i < arr.length; i++) {
            if (temp1[0].equals(arr[i])) {
                index = i;
                break;
            }
        }
        return index;
    }
}

class Dish { // 菜品类:对应菜谱上一道菜的信息。
    String name;// 菜品名称

    int unit_price; // 单价

    boolean isSpecialty;

    public Dish() {

    }

    public Dish(String name, int unit_price, boolean isSpecialty) {
        this.name = name;
        this.unit_price = unit_price;
        this.isSpecialty = isSpecialty;
    }

    int getPrice(int portion) {
        int price = 0;
        switch (portion) {
            case 1:
                price = unit_price;
                break;
            case 2:
                price = (int) Math.round((float) unit_price * 1.5);
                break;
            case 3:
                price = unit_price * 2;
                break;
        }
        return price;
    }
}

class Menu { // 菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
    Dish[] dishs = new Dish[100];// 菜品数组,保存所有菜品信息
    int count = 0;

    public Menu() {

    }

    Dish searthDish(String dishName) { // 根据菜名在菜谱中查找菜品信息,返回Dish对象。
        for (int i = 0; i < count; i++) {
            if (dishName.equals(dishs[i].name)) { // 找得到
                return dishs[i];
            }
        }
        return null;
    }

    Dish addDish(String dishName, int unit_price, boolean isSpecialty) {// 添加一道菜品信息
        if (unit_price > 0 && unit_price < 300) {
            for (int i = 0; i < count; i++) {
                if (dishName.equals(dishs[i].name)) { // 相同菜品
                    dishs[i].unit_price = unit_price;
                    dishs[i].isSpecialty = isSpecialty;
                    return dishs[i];
                }
            }
            Dish newDish = new Dish(dishName, unit_price, isSpecialty);
            dishs[count] = newDish;
            count++;
            return newDish;
        }
        System.out.println(dishName + " price out of range " + unit_price);
        return null;
    }
}

class Record {// 点菜记录类:保存订单上的一道菜品记录
    int orderNum;// 序号

    Dish dish;// 菜品

    int portion;// 份额(1/2/3代表小/中/大份)

    int num;

    public Record() {

    }

    public Record(int orderNum, Dish dish, int portion, int num) {
        this.orderNum = orderNum;
        this.dish = dish;
        this.portion = portion;
        this.num = num;
    }

    int getPrice() {// 计价,计算本条记录的价格
        return dish.getPrice(portion) * num;
    }
}

class Order { // 订单类:保存用户点的所有菜的信息。
    Record[] records = new Record[100]; // 保存订单上每一道的记录
    int count = 0;
    int sum = 0;
    int[] delNums = new int[60]; // 保存删除序号
    int delCount = 0; // 删除个数
    String[] sentences = new String[60]; // 保存语句
    int senCount = 0;

    public Order() {

    }

    public int getTotalPrice() { // 计算订单的总价
        int sum = 0;
        for (int i = 0; i < count; i++) {
            sum += records[i].getPrice();
        }
        return sum;
    }

    public int getSpecialtyPrice() { // 特色菜总价
        int sum = 0;
        for (int i = 0; i < count; i++) {
            if (records[i].dish.isSpecialty) {
                sum += records[i].getPrice();
            }
        }
        return sum;
    }

    Record addARecord(int orderNum, String dishName, int portion, int num, Menu menu, boolean isAdd) {// 添加一条菜品信息到订单中。
        if (count > 0) {
            if (orderNum <= records[count - 1].orderNum) { // 不按顺序
                addSentence("record serial number sequence error");
                return null;
                // System.out.println("record serial number sequence error");
            }
        }
        Dish dish = menu.searthDish(dishName);
        if (dish == null) { // 菜名不存在
            addSentence(dishName + " does not exist");
            // System.out.println(dishName + " does not exist");
            return null;
        }
        if (dish.isSpecialty == true && (portion == 1 || portion == 2)) { // 特色菜份额1、2

        } else if (dish.isSpecialty == false && portion >= 1 && portion <= 3) { // 普通菜份额1、2、3

        } else { // 份额超出范围
            addSentence(orderNum + " portion out of range " + portion);
            // System.out.println(orderNum + " portion out of range " + portion);
            return null;
        }
        if (num <= 15) { // 份数不超过15
            for (int i = 0; i < count; i++) { // 菜名和份额一样,份数相加
                if (dishName.equals(records[i].dish.name) && portion == records[i].portion) { // 同一桌菜名、份额相同的点菜记录要合并成一条进行计算
                    records[i].num += num;
                    return records[i];
                }
            }
            Record newRecord = new Record(orderNum, dish, portion, num);
            records[count] = newRecord;
            count++;
            if (isAdd) {
                addSentence(orderNum + " " + dishName + " " + newRecord.getPrice());
            }
            // System.out.println(orderNum + " " + dishName + " " + newRecord.getPrice());
            return newRecord;
        } else { // 份数超出范围
            addSentence(orderNum + " num out of range " + num);
            // System.out.println(orderNum + " num out of range " + sum);
            return null;
        }
    }

    void delARecordByOrderNum(int orderNum) {// 根据序号删除一条记录
        for (int i = 0; i < delCount; i++) {
            if (orderNum == delNums[i]) {
                addSentence("deduplication " + orderNum);
                // System.out.println("deduplication " + orderNum); // 删除序号重复
                return;
            }
        }
        delNums[delCount] = orderNum;
        delCount++;
        for (int i = 0; i < count; i++) {
            if (orderNum == records[i].orderNum) { // 有删除序号
                for (int j = i; j < count; j++) {
                    records[j] = records[j + 1];
                }
                count--;
                return;
            }
        }
        System.out.println("delete error");
    }

    Record findRecordByNum(int orderNum) {// 根据序号查找一条记录
        for (int i = 0; i < count; i++) {
            if (orderNum == records[i].orderNum) {
                return records[i];
            }
        }

        return null;
    }

    public void addSentence(String str) {
        sentences[senCount] = str;
        senCount++;
    }

    public void showSentence() {
        for (int i = 0; i < senCount; i++) {
            System.out.println(sentences[i]);
        }
    }

}

class Table { // 桌类:保存一桌的信息
    int tableNum; // 桌号

    int year;
    int month;
    int day;

    int hour;
    int minute;
    int second;

    Order order;

    int dayOfWeek;

    String[] dayOfWeekStrings = { "0", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };

    public Table() { // 无参构造方法

    }

    public Table(int tableNum, int year, int month, int day, int hour, int minute, int second, int dayOfWeek,
            Order order) { // 带参构造方法
        this.tableNum = tableNum;
        this.year = year;
        this.month = month;
        this.day = day;
        this.hour = hour;
        this.minute = minute;
        this.second = second;
        this.dayOfWeek = dayOfWeek;
        this.order = order;
    }

    public int getOriginalPrice() {
        return order.getTotalPrice();
    }

    public int getDiscountPrice() {
        if (dayOfWeek >= 6 && dayOfWeek <= 7) {
            return order.getTotalPrice();
        } else if (dayOfWeek >= 1 && dayOfWeek <= 5) {
            double discount = 0;
            if (hour >= 10 && hour <= 14) {
                discount = 0.6;
            } else if (hour >= 17 && hour <= 20) {
                discount = 0.8;
            }
            return (int) Math.round((double) (order.getTotalPrice() - order.getSpecialtyPrice()) * discount
                    + (double) order.getSpecialtyPrice() * 0.7);
        }
        return 0;
    }

}

class Tables { // 保存每桌的信息
    Table[] table = new Table[60];
    int count = 0;
    int tableNum; // 桌号

    int year;
    int month;
    int day;

    int hour;
    int minute;
    int second;

    int dayOfWeek;

    public Tables() {

    }

    public Table addTable(int tableNum, int year, int month, int day,
            int hour, int minute, int second, int dayOfWeek) {
        if (tableNum >= 1 && tableNum <= 55) {
            Table preTable = findTableByNum(tableNum);
            if (preTable == null) { // 新桌号
                if (checkTimeValidity(tableNum, year, month, day, hour, minute, second)) {
                    if (isDuringTime(tableNum, dayOfWeek, hour, minute, second)) {
                        Table newTable = new Table(tableNum, year, month, day, hour, minute, second, dayOfWeek,
                                new Order());
                        table[count] = newTable;
                        table[count].order.addSentence("table " + tableNum + ": ");
                        count++;
                        return newTable;
                    }
                }
            } else { // 相同桌号
                if (isSameTable(dayOfWeek, preTable.year, year, preTable.month, month, preTable.day, day,
                        preTable.hour, hour, preTable.minute, minute, preTable.second, second)) {
                    // 同一时间
                    return preTable;
                } else { // 不同时间
                    if (checkTimeValidity(tableNum, year, month, day, hour, minute, second)) {
                        if (isDuringTime(tableNum, dayOfWeek, hour, minute, second)) {
                            Table newTable = new Table(tableNum, year, month, day, hour, minute, second, dayOfWeek,
                                    new Order());
                            table[count] = newTable;
                            count++;
                            return newTable;
                        }
                    }
                }
            }
        } else { // 桌号超出范围
            if (count != 0) {
                table[count].order.addSentence(tableNum + " table num out of range");
            } else {
                System.out.println(tableNum + " table num out of range");
            }
        }
        return null;
    }

    public Table findTableByNum(int tableNum) { // 序号找桌子
        for (int i = 0; i < count; i++) {
            if (tableNum == table[i].tableNum) {
                return table[i];
            }
        }
        return null;
    }

    public Table findTableByInedx(int index) {
        if (index >= 0 && index <= count) {
            return table[index];
        }
        return null;
    }

    public boolean checkTimeValidity(int tableNum, int year, int month, int day, int hour, int minute, int second) {
        int[] mon_maxnum = new int[] { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        if (month >= 1 && month <= 12 && day >= 1 && day <= mon_maxnum[month]
                && hour >= 0 && hour < 24 && minute >= 0
                && minute < 60 && second >= 0 && second < 60) {
            if (year >= 2022 && year <= 2023) {
                return true;
            } else {
                if (count != 0) {
                    table[count].order.addSentence("not a valid time period");
                } else {
                    System.out.println("not a valid time period");
                }
            }
        } else {
            if (count != 0) {
                table[count - 1].order.addSentence(tableNum + " date error");
            } else {
                System.out.println(tableNum + " date error");
            }
        }
        return false;
    }

    public boolean isDuringTime(int tableNum, int dayOfWeek, int hour, int minute, int second) {
        if (dayOfWeek >= 1 && dayOfWeek <= 5) {
            if (hour == 10) {
                if (minute >= 30 && minute < 60 && second >= 0 && second < 60) {
                    return true;
                }
            } else if (hour == 20 || hour == 14) {
                if (minute == 30 && second == 0) { // 20 : 30; 14 : 30
                    return true;
                } else if (minute >= 0 && minute < 30 && second >= 0 && second < 60) {
                    return true;
                } else {
                    if (count != 0) {
                        table[count].order.addSentence("table " + tableNum + " out of opening hours");
                    } else {
                        System.out.println("table " + tableNum + " out of opening hours");
                    }
                    return false;
                }
            } else if ((hour >= 17 && hour <= 19) || (hour >= 11 && hour <= 13)) {
                if (minute >= 0 && minute < 60 && second >= 0 && second < 60) {
                    return true;
                } else {
                    if (count != 0) {
                        table[count].order.addSentence("table " + tableNum + " out of opening hours");
                    } else {
                        System.out.println("table " + tableNum + " out of opening hours");
                    }
                    return false;
                }
            }
        } else if (dayOfWeek >= 6 && dayOfWeek <= 7) {
            if (hour == 9) {
                if (minute >= 30 && minute < 60 && second >= 0 && second < 60) {
                    return true;
                }
            } else if (hour == 21) {
                if (minute == 30 && second == 0) { // 21 : 30
                    return true;
                } else if (minute >= 0 && minute < 30 && second >= 0 && second < 60) {
                    return true;
                } else {
                    if (count != 0) {
                        table[count].order.addSentence("table " + tableNum + " out of opening hours");
                    } else {
                        System.out.println("table " + tableNum + " out of opening hours");
                    }
                    return false;
                }
            } else if (hour >= 10 && hour <= 20) {
                if (minute >= 0 && minute < 60 && second >= 0 && second < 60) {
                    return true;
                } else {
                    if (count != 0) {
                        table[count].order.addSentence("table " + tableNum + " out of opening hours");
                    } else {
                        System.out.println("table " + tableNum + " out of opening hours");
                    }
                    return false;
                }
            }
        }
        return false;
    }

    public boolean isSameTable(int dayOfWeek, int year1, int year2, int month1, int month2, int day1, int day2,
            int hour1, int hour2, int minute1, int minute2, int second1, int sceond2) { // 是否为同一桌
        if (year1 == year2 && month1 == month2 && day1 == day2) { // 同一天
            if (dayOfWeek >= 1 && dayOfWeek <= 5) { // 周一至周五
                if (hour1 >= 17 && hour1 <= 20 && hour2 >= 17 && hour2 <= 20) { // 晚上
                    return true;
                } else if (hour1 >= 10 && hour1 <= 14 && hour2 >= 10 && hour2 <= 14) { // 中午
                    return true;
                } else {
                    return false;
                }
            } else if (dayOfWeek >= 6 && dayOfWeek <= 7) { // 周末
                if (getTime(hour1, hour2, minute1, minute2, second1, sceond2) < 3600) { // 一小时内
                    return true;
                } else {
                    return false;
                }
            }
        } else { // 不是同一天
            return false;
        }
        return false;
    }

    public long getTime(int hour1, int hour2, int minute1, int minute2, int second1, int second2) {
        // 计算时间差,精确到秒
        long sum1 = hour1 * 3600 + minute1 * 60 + second1;
        long sum2 = hour2 * 3600 + minute2 * 60 + second2;
        return Math.abs(sum1 - sum2);
    }

    public void showTables() {
        for (int i = 0; i < count; i++) {
            table[i].order.showSentence();
        }
        for (int i = 0; i < count; i++) {
            System.out.println("table " + table[i].tableNum + ": " + table[i].getOriginalPrice() + " "
                    + table[i].getDiscountPrice());
        }
    }

}

踩坑心得

OOP训练集04 7-2有重复数据
题目:在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。
你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,输出“YES”这三个字母;如果没有,则输出“NO”。

import java.util.Scanner;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        boolean flag = false;
        int[] array = new int[n];
        for (int i = 0; i < n; i++) {
            array[i] = sc.nextInt();
        }
        Arrays.sort(array);
        for (int i = 0; i < n - 1; i++) {
            if (array[i] == array[i + 1]) {
                flag = true;
                break;
            }
        }
        if (flag == true) {
            System.out.println("YES");
        } else {
            System.out.println("NO");
        }
        sc.close();
    }
}


虽然说做对了,但想试试上课老师介绍过ArrayList和Collections方法

import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        boolean flag = false;
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        for (int i = 0; i < n; i++) {
            arrayList.add(sc.nextInt());
        }
        Collections.sort(arrayList);
        for (int i = 0; i < n - 1; i++) {
            System.out.println(arrayList.get(i));
            System.out.println(arrayList.get(i + 1));
            if (arrayList.get(i) == arrayList.get(i + 1)) {
                flag = true;
                break;
            }
        }
        if (flag == true) {
            System.out.println("YES");
        } else {
            System.out.println("NO");
        }
        sc.close();
    }
}


踩坑与心得:运行超时,这很符合ArrayList慢的特性

OOP训练集04 7-3 去掉重复的数据
题目:在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。
你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,去掉所有重复的数字。最后按照输入顺序输出没有重复数字的数据。所有重复的数字只保留第一次出现的那份。

import java.util.HashSet;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int cnt = 0;
        HashSet<Integer> seen = new HashSet<Integer>();
        for (int i = 0; i < n; i++) {
            boolean flag = seen.add(sc.nextInt());
            if (flag == true) {
                cnt++;
            }
        }
        for (int num : seen) {
            System.out.print(num);
            if (cnt-- != 1) {
                System.out.print(" ");
            }
        }
        sc.close();
    }
}


踩坑与心得:使用HashsetSet确实会慢一些导致运行超时,但答案错误却找不出原因。


询问同学后,用StringBuilder来储存该字符串,最后输出即可

import java.util.HashSet;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        StringBuilder sb = new StringBuilder();
        HashSet<Integer> seen = new HashSet<Integer>();
        for (int i = 0; i < n; i++) {
            int num = sc.nextInt();
            boolean flag = seen.add(num);
            if (flag == true) {
                sb.append(num).append(" ");
            }
        }
        sb.deleteCharAt(sb.length() - 1);
        String str = sb.toString();
        System.out.println(str);
        sc.close();
    }
}

OOP训练集04 7-7 判断两个日期的先后,计算间隔天数、周数
题目:从键盘输入两个日期,格式如:2022-06-18。判断两个日期的先后,并输出它们之间间隔的天数、周数(不足一周按0计算)。

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String dateString1 = sc.nextLine();
        LocalDate date1 = LocalDate.parse(dateString1);
        String dateString2 = sc.nextLine();
        LocalDate date2 = LocalDate.parse(dateString2);

        if (date1.isBefore(date2)) {
            System.out.println("第一个日期比第二个日期更早");
        } else if (date1.isAfter(date2)) {
            System.out.println("第一个日期比第二个日期更晚");
        }

        long daysBetween = Math.abs(date1.until(date2, ChronoUnit.DAYS));
        System.out.println("两个日期间隔" + daysBetween + "天");

        long weeksBetween = (long) (daysBetween / 7.0);
        System.out.println("两个日期间隔" + weeksBetween + "周");
        sc.close();
    }
}

踩坑与心得:输入的日期不符合yyyy-mm-dd时,报错

自定义一个名为trans的方法将输入的日期格式转换为yyyy-mm-dd即可

public static String trans(String str) { // 转换日期标准格式
    String[] parts = str.split("-");
    StringBuilder sb = new StringBuilder();
    sb.append(parts[0]);
    sb.append("-");
    if (parts[1].length() == 1) {
        sb.append("0");
    }
    sb.append(parts[1]);
    sb.append("-");
    if (parts[2].length() == 1) {
        sb.append("0");
    }
    sb.append(parts[2]);
    return sb.toString();
}

OOP训练集05 7-4 正则表达式训练-学号校验

import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.nextLine();
		String regex = "2020(1[1-7]|61|7[1-3]|8[1-2])([0-3][0-9]|40)";
		if (str.matches(regex)) {
			System.out.println("正确");
		} else {
			System.out.println("错误");
		}
		sc.close();
	}
}


踩坑与心得:学号(序号)包含了00,导致错误,修改正则表达式为"2020(1[1-7]|61|7[1-3]|8[1-2])(0[1-9]|[1-3][0-9]|40"即可限定学号为01~40

import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.nextLine();
		String regex = "2020(1[1-7]|61|7[1-3]|8[1-2])(0[1-9]|[1-3][0-9]|40)";
		if (str.matches(regex)) {
			System.out.println("正确");
		} else {
			System.out.println("错误");
		}
		sc.close();
	}
}

改进建议

  • 在Array、ArrayList、LinkedList的使用上要有所选择。
    • 长度确定且数据较小时使用Array,速度快,占内存小,操作简单;长度不确定且对元素的访问需求较多是,使用ArrayList,访问元素较快且ArrayList会自动扩容防止越界的情况出现;当对数据进行插入、删除操作需求较多时,使用LinkedList,插入、删除的速度更快,由于每一个节点都要储存引用,耗内存的缺点也很明显。
    • Array是一个固定大小的容器,底层采用的是线性连续空间来存放元素。优点在于在内存中是连续的,速度较快,操作简单。缺点是定义数组时要定义其长度,不是很灵活,过长过短都会造成问题。不方便进行数据的添加、插入和移除。
    • ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。
    • 与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。
    • 相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
    • LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。
  • 需要输出一行很多个数据时,不使用循环一个一个输出,而直接使用StringBuilder不断append进行拼接。
    • 因为每次虚拟机碰到"+"这个操作符对字符串进行拼接地时候会new出一个StringBuilder,然后调用append方法,最后调用toString()方法转换字符串赋值给对象,所以循环多少次,就会new出多少个StringBuileder()来,这对于内存是一种浪费。

总结

  • 这三次题目集,学了
    • Array、ArrayList、LinkedList的使用,
    • Hashset的使用
    • LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则
    • ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法,正则表达式的使用
    • 正则表达式的使用
    • 面向对象编程的封装性
    • 面向对象设计的聚合关系
  • 最大的收获是坚韧不拔的精神
  • 建议
    • 提高作业难度时勿跨度太大,可以先练习菜单计价程序-4系列前的PTA题目,而且此系列的题目描述相关联,能更容易理解题目描述意思,而且难度上升跨度不会太大。
    • 题目集练习的知识点落后于上课内容,希望练习能跟上上课内容,更好地练习巩固学到的知识。