题目集4~6的总结性Blog
作者:互联网
前言:
这个月的java学习,同样也是让我们学会了很多东西,关于知识点的话,主要集中在对类这一大模块的语法,创建,构建,类与类之间的关系的了解 ,还外加对正则表达式的使用,但这次的正则表达式相对与上次对正则表达式的使用难度,明显提高,可谓是一次跃升,这次的题目还涉及到对Map,List的使用,让我们初步了解到java中的"链表".总体来说的话,三次题目集的整体难度在逐渐下滑,但题量以及涉及到的知识点也变得多了起来,细分三周的作业的话,第四周是对正则表达式的第一次增强,还是对类设计,类之间关系的初步了解,大家通过自己实现类与类之间关系而得到自己的感悟.第五周是对我们LIst,Map接口的使用,同样的,我们也是编写了正则表达式的题目,还迭代了第四周的日期类,但该次迭代使用的是聚合的方法,相对与之前使用的那种方法也是更加的安全,且维护性好.第六周的题目相对与之前的题目集,难度大幅度降低,但是也包含了新的知识多态和接口.大致的分析如此.
设计与分析:
①题目集4(7-2)、题目集5(7-4)两种日期类聚合设计的优劣比较
1).单独分析题目集4(7-2)
题目集合四7-2个人理解及思路:类图相当多细节,其类与类之间的联系是有DateUtil用Day联系Month,再用Month联系Year,环环相扣,相当于用线穿起来,调用之间可以做到相对直接的调用方法去实现一个整体的功能,每个类有有莫大的联系.做题的思路的话,直接从底层类Year开始构造整个框架,依次完善各个类,利用好类与类之间函数的相互调用,可以简化最后的操作,且思路清晰.(例:Month类中判断数据是否合理时,可以同时调用Year类里的数据是否合理的函数进行判断).整个程序写起来还是可以说是思路清晰,目标明确.话不多说,上代码:
核心代码:DateUtil类
class DateUtil { Day day; public DateUtil() { } public DateUtil(int d,int m,int y) { Year year = new Year(y); Month month = new Month(m,year); Day day = new Day(d,month); this.day = day; } public Day getDay() { return day; } public void setDay(Day day) { this.day = day; } public boolean checkInputValidity() { if(day.validate()) { return true; } return false; } public boolean compareDates(DateUtil date) { //date在day前则返回true int date1_year= day.getMonth().getYear().getVakue() ; int date2_year = date.getDay().getMonth().getYear().getVakue(); if(date1_year < date2_year) { return true; } else if(date1_year == date2_year) { int date1_month = day.getMonth().getValue(); int date2_month = date.getDay().getMonth().getValue(); if(date1_month < date2_month) { return true; } else if(date1_month == date2_month) { int date1_day = day.getValue(); int date2_day = date.getDay().getValue(); if(date1_day < date2_day) { return true; } else return false; } else return false; } else return false; } public boolean equalTwoDates(DateUtil date) { int date1_year= day.getMonth().getYear().getVakue() ; int date2_year = date.getDay().getMonth().getYear().getVakue(); int date1_month = day.getMonth().getValue(); int date2_month = date.getDay().getMonth().getValue(); int date1_day = day.getValue(); int date2_day = date.getDay().getValue(); if(date1_year == date2_year) { if(date1_month == date2_month) { if(date1_day == date2_day) return true; else return false; } else return false; } else return false; } public String showDate() { int month_1 = day.getMonth().getValue(); int year_1 = day.getMonth().getYear().getVakue(); int day_1 = day.getValue(); String Date =""+ year_1; if(month_1<10) { Date = Date + "-" + month_1; } else { Date = Date + "-" + month_1; } if(day_1<10) { Date = Date + "-" + day_1; } else { Date = Date + "-" + day_1; } return Date; } public DateUtil getNextNDays(int n) { Day day = this.day; for(int i = 0;i < n;i++) day.dayIncrement(); int y = day.getMonth().getYear().getVakue(); int m = day.getMonth().getValue(); int d = day.getValue(); DateUtil date = new DateUtil(d,m,y); return date; } public DateUtil getPreviousNDays(int n) { Day day = this.day; for(int i = 0;i < n;i++) day.dayReduction(); int y = day.getMonth().getYear().getVakue(); int m = day.getMonth().getValue(); int d = day.getValue(); DateUtil date = new DateUtil(d,m,y); return date; } public int getDaysofDates(DateUtil date) { if(equalTwoDates(date)) { return 0; } else if(compareDates(date)==false) { int js = 0; while(equalTwoDates(date) == false) { js++; date.getNextNDays(1); } return js; } else { int js = 0; while(equalTwoDates(date)==false) { js++; date.getPreviousNDays(1); } return js; } } }
圈复杂度的分析:
代码最终的圈复杂度升序排列:
总体性能分析:相对于前几次的作业,对switch和if的了解已经很深,对使用循环对复杂度影响的概念也有了一定概念.在Main类中使用的更改为switch,我认为当前程序不足的是在DateUtil类中写的求下几天及求前几天需要得到改进,在该方法中,使用的是循环求前一天得到的,完全没有如何的优化,使用暴力求解的,但在之后我认为如果数据够大,完全可以求到下一年的1.1日,然后直接进行跨年相加,到同年时可以进行相加月份天数,可以大大的减少运行时间,对大数据的处理更加友好.
2).单独分析题目集5(7-4)
题目集合五7-4个人理解及思路:这道题依旧是从箭头的末端开始,先构造year,day,month类,然后在构建DateUtil类,进而实现日期的聚合关系,主要是由DatUtil类来管理,类与类之间的关系满足"不和陌生人生活"的理念,虽然层次不够清晰,但构建的理念清晰,且可维护性强, 可以实现较方便的实现对方法的添加,以及对类的修改,简而言之就是方便进行改造或者升级,进行迭代.
核心代码:DateUtil类
class DateUtil { Day day; Year year; Month month; int[] mon_maxnum = {31,28,31,30,31,30,31,31,30,31,30,31}; public DateUtil() { } public DateUtil(int d,int m,int y) { year = new Year(y); month = new Month(m); day = new Day(d); } public Day getDay() { return day; } public void setDay(Day day) { this.day = day; } public Year getYear() { return year; } public void setYear(Year year) { this.year = year; } public Month getMonth() { return month; } public void setMonth(Month month) { this.month = month; } public void setDayMax() { if(year.isLeapYear()&&month.value == 2) { day.value = 29; }else { day.value = mon_maxnum[month.value-1]; } } public void setDayMin() { day.value = 1; } public boolean checkInputValidity() { if(month.value < 1 || month.value > 12) { return false; } if(day.value > 0 && day.value <= mon_maxnum[month.value-1] &&year.validate()&&month.validate()) { return true; } return false; } public boolean compareDates(DateUtil date) { //date在day前则返回true if(year.value < date.year.value) { return true; } else if(year.value == date.year.value) { if(month.value < date.month.value) { return true; } else if(month.value == date.month.value) { if(day.value < date.day.value) { return true; } else return false; } else return false; } else return false; } public boolean equalTwoDates(DateUtil date) { if(year.value == date.year.value) { if(month.value == date.month.value) { if(day.value == date.day.value) return true; else return false; } else return false; } else return false; } public String showDate() { String Date =""+ year.value; Date = Date + "-" + month.value; Date = Date + "-" + day.value; return Date; } public DateUtil getNextNDays(long nest) { DateUtil date = this; for(int i = 0;i < nest;i++) { if(year.isLeapYear()&&month.value == 2) { if(day.value == 29) { month.monthIncrement(); day.value = 1; }else { day.dayIncrement(); } }else { if(day.value == mon_maxnum[month.value - 1]) { if(month.value == 12) { day.value = 1; month.resetMin(); year.yearIncrement(); }else { month.monthIncrement(); day.value = 1; } }else { day.dayIncrement(); } } } return date; } public DateUtil getPreviousNDays(long nest1) { DateUtil date = this; for(int i = 0;i < nest1;i++) { if(day.value == 1) { if(month.value == 1) { month.resetMax(); day.value = mon_maxnum[month.value -1]; year.yearReduction(); }else if(month.value == 3 ){ if(year.isLeapYear()) { month.monthReduction(); day.value = 29; }else { month.monthReduction(); day.value = 28; } }else { month.monthReduction(); day.value = mon_maxnum[month.value -1]; } }else { day.dayReduction(); } } return date; } public int getDaysofDates(DateUtil date) { if(equalTwoDates(date)) { return 0; } else if(compareDates(date)==false) { int js = 0; while(equalTwoDates(date) == false) { js++; date = date.getNextNDays(1); } return js; } else { int js = 0; while(equalTwoDates(date)==false) { js++; date = date.getPreviousNDays(1); } return js; } } }
圈复杂度的分析:
整体代码最终的圈复杂度:
总体性能分析和改善意见:对使用循环对复杂度影响的概念也有了一定概念,尽可能避免使用if语句,且用switch代替,改善意见的话,和之前日期类聚合1得到想法相似,就是当前程序不足的是在DateUtil类中写的求下几天及求前几天需要得到改进,在该方法中,使用的是循环求前一天得到的,完全没有如何的优化,使用暴力求解的,但在之后我认为如果数据够大,完全可以求到下一年的1.1日,然后直接进行跨年相加,到同年时可以进行相加月份天数,可以大大的减少运行时间,对大数据的处理更加友好.
两种日期类聚合设计的优劣比较:
第一种:
优点:层次清晰,类与类之间层层交替,关系紧密.
缺点:类与类之间关系过于紧密,若程序出现bug或者需要举行修改导致大部分代码受到波及,所以不易更改.
第二种:
优点:day,month,year类之间没有如何关系,符合"不要和陌生人说话"的面向对象编程理念,便于修改和增添内容
缺点:类与类之间的关系太过浅薄, 编写过程实现功能时调用以及计算都没有日期类聚合1中好用.
②.题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)
1).单独分析题目集4(7-3)
类图如下
题目分析及自我理解:这道题是题目集4中最简单的一道题,这道题的层次十分清晰,构建父类后创建子类,继续创建子类继承其即可,其关系为父类Shape,还有三个子类Circle,Rectangle,Ball,Box。Circle和Rectangle继承Shape,而Ball继承Circle,Box继承Rectangle。此次题目涉及到的知识点就是对类继承的了解,调用构造函数时实际调用的情况.值得一谈的是,在Ball类中没有创建自己的属性,这是因为在调用构造方法时,用super实现调用父类构造方法来更改属性.
圈复杂度的分析:
整体代码最终的圈复杂度:
总体性能分析和改善意见:这个题目相对简单,难度不大,性能应该是较高的,算法优化的话暂时没有。
2).单独分析题目集6(7-5)
类图如下:
题目分析及自我理解:这次的题目名图形继承与多态,是上次图形类的迭代,也是我们第一次接触到多态这个知识点,在这里懂得多态的概念以及存在意义。对于这个题目图形类我们已经不是第一次了,总体相对于之前的题目来说难度偏低,但涉及到了我们未曾接触的多态。对于这个题目的理解,可以说是收获颇深,主要是懂得了多态的概念以及意义,感觉自己更加的接近面向对象的思维,当然不仅如此,对多态的使用的好坏也是可以让我们可以省下很多的多余时间,编译出高质量代码。
圈复杂度的分析:
整体代码最终的圈复杂度:
总体性能分析和改善意见:这次的排序我选择了比冒泡排序更快的插入排序(用List包里的类),复杂度的呈现也是相对满意,对于这种插入数据的形式,插入排序应该是最快的排序方式。且用链表实现不占空间,空间复杂度也是可以得到很好的优化。改善意见的话就是可以使用java自带的排序函数,速度可以更快且编译较方便,可以得到较好的效果。
3).单独分析题目集6 (7-6)
类图如下:
题目分析及自我理解:还是一道图形类的迭代,其中过程也是比较熟悉,但这次的图形类的迭代中要求添加GetArea接口,对接口的编写也是比较简单易学的,java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。在不同子类中,完成实现方法的代码内容。这次主要是从不同方向了解到了面向对象的设计思维,对接口的理解为构造整体框架后实现方法,题目相对简单却收获不浅。
圈复杂度的分析:
整体代码最终的圈复杂度:
总体性能分析和改善意见:这次的题目较小且简单导致性能都快,可以减少的复杂度主要是if语句和switch语句的使用吧,改善的话就是接口的完善度,可以在接口中定义该定义的属性,深刻了解到接口的优点是多方面的,接口能够让代码更规范,可以给开发人员更清晰的指示,一个接口可以去实现一系列的功能。而且接口可以加强代码的可维护性,当程序需要改变的时候,可以做到只改变一个类而不改变接口。遵循面向对象的思维方式。
题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)的总体分析:
主要是对接口以及父类的理解,接口是完全抽象的,可以用于构建整体框架,但难以实现规划未来需要添加的方法,但父类的话可以实现,可以理解为接口是完全抽象的类的“父类”,封装主要是为了将抽象的物质具体话,可以用各个类去丰富该封装的对象,具象话该对象,这同样也是面向对象的思维方式。对于多态的话,他也是面向对象必不可少的一部分,多态的实现使得类与类之间可以相互转换,这同样也是面向对象的思维方式,可以简化抽象的物质或者问题.
③对三次题目集中用到的正则表达式技术的分析总结
题目集4 ---7-1:
判断条件:① 测量时间:格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],“年”非 4 位数时, 之前不加“0”,“月”与“日”为一位数时之前也不加“0”,日期与时间之间有一个空格, “时”与“分”之间采用冒号分隔(英文半角),“时”为一位数时之前不加“0”,“分” 始终保持两位且始终为“00”(即整点)。注意:“时”数必须是 24 小时进制中的偶数值 ② 目标水位、实际水位、流量:均为实型数,取值范围为[1,1000),小数点后保留 1-3 位小数 或无小数(此时不需要写小数点) ③ 目标开度、实际开度:实型数,取值范围为[1,10),必须保留 2 位小数,两个开度之间用“/” 分隔
String zq_kd = "[1-9]\\.[0-9]{2}/[1-9]\\.[0-9]{2}"; //开度 String zq_sw = "[1-9]\\d{0,2}((\\.\\d{1,3})?)"; //水位 String zq_sj = "[1-9]\\d" //年 + "{0,3}/[1-9]\\d?" //日期月 + "/[1-9]\\d?\\s" //日期日 + "[12]?[0-9]\\d?:00"; //时间 String dkd ="[1-9]\\.[0-9]{2}"; //单个开度
注:该判断已经使用split函数按 '|' 分开.
开度判断:正则表达式为"[1-9]\\.[0-9]{2}/[1-9]\\.[0-9]{2}" 要求为目标开度、实际开度:实型数,取值范围为[1,10),所以前置为[1-9],由于必须保留 2 位小数,加入.和[0-9]{2},则构成该结构.
水位判断:"[1-9]\\d{0,2}((\\.\\d{1,3})?)" 要求为目标水位、实际水位、流量:均为实型数(同上前置为[1-9]),取值范围为[1,1000)(后接受0-2为小数),小数点后保留 1-3 位小数 或无小数(此时不需要写小数点)(所以用?运算符判断是否有小数点和后缀部分).
判断日期:前面都比较正常后缀还有判断是否为正确的日期.值得注意的是那个空格也就是那个不太起眼的\\s.
统计Java程序中关键词的出现次数
String s = "abstract、assert、boolean、break、byte、case、catch、" + "char、class、const、continue、default、do、double、else、" + "enum、extends、false、final、finally、float、" + "for、goto、if、implements、import、instanceof、" + "int、interface、long、native、new、null、package、" + "private、protected、public、return、short、static、" + "strictfp、super、switch、synchronized、this、throw、" + "throws、transient、true、try、void、volatile、while"; String[] gjz = s.split("、"); //拆分关键字
while(s_1.equals("exit")!=true) { if(s_1.matches(".*//.*")) { // 处理//注释 String[] s_2 = s_1.split("//"); str.append(s_2[0]); }else str.append(" "+s_1); str.append(" "); s_1 = in.nextLine(); }
这两部分分别是拆分从网上查找到的关键字集合,并且删除"//"后的注释,换位" "(空格)便于处理.
String str_1 = str.toString(); Pattern pattern_1 = Pattern.compile("/\\*[\\s\\S]*\\*/"); Matcher matcher_1 = pattern_1.matcher(str_1); //对/**/注释的处理 while(matcher_1.find()) { str = str.replace(matcher_1.start()-1, matcher_1.end()-1, " "); }
这一部分这是使用"/\\*[\\s\\S]*\\*/"判断是否存在/*....*/的注释,有则进行删除.
for(int i = 0; i < 53;i++) { Pattern pattern = Pattern.compile("[()\\[\\*,.;:\\]{}\\s+-/' ']" + list1.get(i) + "[\\[\\*\\],.;:())\\s{}+-/' ']"); int dq = 0; Matcher matcher = pattern.matcher(str); while(matcher.find()) { dq++; } list2.add(dq); }
这一部分则是看其关键字前后是否存在合法字符,不存在则不计入,计入则存入链表.
正则表达式训练-QQ号校验
判断条件:
-
- 要求必须是 5-15 位;
- 0 不能开头;
- 必须都是数字;
if(s.matches("[1-9](\\d{4,14})")) { System.out.println("你输入的QQ号验证成功"); }else { System.out.println("你输入的QQ号验证失败"); }
由于qq号前不可为零则使用"[1-9]",且其长度为5-15.所以后缀的\\d(数字)应当为4到14为.
验证码校验
判断条件:验证码是由四位数字或者字母(包含大小写)组成的字符串。
if(s.matches("[0-9a-zA-Z]{4}")) { System.out.println( s +"属于验证码"); }else { System.out.println(s + "不属于验证码"); }
可为数字加入"0-9",可为字母加入"a-z"和"A-Z",为四位加入{4};
学号验证
判断格式:
对软件学院2020级同学学号进行校验,学号共八位,规则如下:
- 1、2位:入学年份后两位,例如20年
- 3、4位:学院代码,软件学院代码为20
- 5位:方向代码,例如1为软件工程,7为物联网
- 6位:班级序号
- 7、8位:学号(序号)
if(s.matches("2020((1[1-7])|(61)|(7[1-3]))([1-3][0-9])|(40)")) { System.out.println("正确"); }else { System.out.println("错误"); }
按班型分为1开头和7开头,6开头,分为这几部分,后缀也分为1-39和40的情况即得到改正则表达式
④题目集5(7-4)中Java集合框架应用的分析总结
题目集5(7-4)使用的是聚合,这也是当前面向对象编程方式最认可的一种形式,"符合不和陌生人说话"的原则,这种编程方式,是现在大家普遍认可且优秀的编程方式,这种编程方式也是以后大家在公司进行编写的一种要求,主要是可以让类与类之间减少交互甚至没有交互,可以增加改代码的维护性以及升级,增加功能时的简便性,使得每个板块独立,这样做使得单个板块的复用性变得很高,在修改时可以做到直接治根治本的效果,对其他的类的影响可以降到最低,使得该程序不会受到致命的bug(若遇到bug且类与类之间交互太多,可以使得多方程序崩溃),进而使得该程序的可维护性也得到增强,每个板块做每个板块的事情完全符合单一职责的原则.这种集合框架可维护性强,且相对于非聚合关系的代码来说更加安全,可以增加代码的独立性和稳定性.
(3)采坑心得:对源码的提交过程中出现的问题及心得进行总结,务必做到详实,拿数据、源码及测试结果说话,切忌假大空
1.题目集3 7-1中,校验类对单个数据的处理有问题
原代码存在问题:只可以进行一组大数据进行处理,没有考虑分层处理,使得整体的效果都很差,判断吃力;
改进代码:
public String[] getData() { // 按|分离字符串 String [] str = data.split("\\|"); return str; }
分析:增加拆分该数据的方法.
String zq_kd = "[1-9]\\.[0-9]{2}/[1-9]\\.[0-9]{2}"; //开度 String zq_sw = "[1-9]\\d{1,2}((\\.\\d{1,3})?)"; //水位 String zq_sj = "[1-9]\\d" //年 + "{0,3}/[1-9]\\d?" //日期月 + "/[1-9]\\d?\\s" //日期日 + "[12]?[0-9]\\d?:00"; //时间 String dkd ="[1-9]\\.[0-9]{2}"; //单个开度
分析:增加单个数据的分析,使用分开处理,明了清晰;
2. 题目集4 7-2day类中判断是否正确
原代码存在问题:没有先判断月分是否正确则直接判断该月份下的天数是否正确导致月份越界(例如13月,但在mon_maxnum数组中,其最大为12);
改进代码:
public void dayIncrement() { if(month.getValue()==2&&month.getYear().isLeapYear()) { if(value==29) { month.monthIncrement(); resetMin(); } else { value++; } } else { if(value==mon_maxnum[month.getValue()-1]) { month.monthIncrement(); resetMin(); } else { value++; } } }
3. 题目集5 7-5DataUtyil类中判断是否正确
原代码存在的问题:与上方几乎一致,没有先判断月分是否正确则直接判断该月份下的天数是否正确导致月份越界(例如13月,但在mon_maxnum数组中,其最大为12);
改进代码:
public boolean checkInputValidity() { if(month.value < 1 || month.value > 12) { return false; } if(day.value > 0 && day.value <= mon_maxnum[month.value-1] &&year.validate()&&month.validate()) { return true; } return false; }
4. 题目集5 7-4正则表达式不完全
原代码存在问题:正则表达式无法全部列举出所有情况或正则表达式运算符的优先级导致与实际想法不符;
改进代码:
Pattern pattern = Pattern.compile("[()\\[\\*,.;:\\]{}\\s+-/' ']" + list1.get(i) + "[\\[\\*\\],.;:())\\s{}+-/' ']");
包括了多种情况:以'(' ')' ' ' '*' ',' 等等情况,且解决了优先级的问题;
5. 题目集5 7-4对注释的处理不到位
原代码存在问题:查找到注释后增添'\n'导致错误
改进代码:
str = str.replace(a, matcher_2.end(), " "); //改成增加空格
str = str.replace(matcher_1.start()-1, matcher_1.end()-1, " ");
(4)改进建议:对相应题目的编码改进给出自己的见解,做到可持续改进
建议: 1 ).对于图形继承,该题的功能太单一,仅仅是一个求面积的方法,不能和日期类一样做到一样的程序结构,使得改图形继承类的题目过于单一,思路清晰,不具备挑战性,但可以用于让同学们了解概念,也是个还有的练手题目,但在第6周却做为压轴题有点偏简单. 2 )对于日期类的创建,我们已经有颇深的经验了,但在创建接口这一块的知识还未与日期类发生碰撞,我认为日期类可以考虑融合接口,成为一个练习接口的难度中等的好题目. 3 ).对于正则表达式的题目,我们已经做过许多,但这些难度几乎可以说仅仅在第二次正则表达式(第四周)就达到改种题目的巅峰难度,后期的难度一直在下降,题目缺少挑战性,且该出题方式不易让同学们适应.
(5)总结:
这一月可谓是收获颇满,相对于上个月学习java的基础语法,这次的内容虽然少,但我们练习的也是十分的熟练,上个月也许学习的量较多,但难度是远远达不到这个月的一半.简单的阐述下这个月学到的东西,对于类的封装,关键词有private , public ,protected,分别代表其在改类中的权限等级,还有继承类之间方法的的关系1.重载 : Overload, 2.覆盖: Overwrite ,3.覆写: Override,也是同样了解到创建父类该有的条件,了解较多的可能就是继承了,继承就是为了实现可复用.而我们刚刚接触的多态:则是不同的对象,接受到同一个消息的时候会产生不同的操作.当然这个月学到的不只是语法还学到了面向对象的编程方式和思维方式,学习了接口,接口的概念,接口的作用,可谓是刚刚进入了面向对象的大门吧!简单来说 这三次作业使我们加深了对正则表达式的理解,学会了继承接口和多态方面的知识,通过实践不断提升自己,相信未来一定能提升很多。
学习建议:可以讲解部分算法题,使得大家对复杂度的了解更多,也是可以让大家更加深刻的了解到编程的有趣及魅力所在.pta的形式也是很不错的一种作业方式,大家实时排名很有挑战性.
意见:相对于之前的题目集,题目的难度大幅度减少,但题目量却在增多,我认为这些增多确实没有太多实质性作用,之前题目集虽然确实有点太难了,但相对于这次的,却偏简单了.
标签:总结性,题目,int,month,Blog,public,year,day 来源: https://www.cnblogs.com/jsnazw/p/14726515.html