题目集4-6的分析及总结
一. 前言
首先,总结一下这三次题目集的我的个人感受及做题情况。从题量上看,三次题目集的题量前俩次题量差不多,后一次题目集题量较多;从题目质量和难度上看,每个题目集都有一俩个难度比较高的题目,所花费时间也需要比较多;从知识点看,这三次题目集,可以分为三个大知识点,一个是日期聚合,一个是正则表达式,一个是图形接口与继承。从我个人感受谈,感觉这三次题目集越做越轻松,主要是掌握了相应的知识点后做题目就会相对轻松,而这三次题目集的题目有类似的题目,所以前面要是掌握了后面做起来就会相对轻松。
二. 设计与分析
-
题目集4(7-2)、题目集5(7-5)两种日期类聚合设计的优劣比较
这俩次题目的需求内容几乎一样,差异的地方就是类的设计有所区别,下面我们来讨论一下这俩个类设计的优劣性:
题目集4(7-2)日期聚合一源码
import java.io.ObjectInputStream; import java.time.YearMonth; import java.util.Date; import java.util.Scanner; /** * @author:everglow * @data 2021/10/20 21:09 */ public class Main { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int choice=sc.nextInt(); DateUtil date=new DateUtil(sc.nextInt(),sc.nextInt(),sc.nextInt()); switch (choice){ case 1: int n1=sc.nextInt(); if(date.checkInputValidity()) { DateUtil date1 = new DateUtil(); date1 = date.getNextNDays(n1); String s = date1.showDate(); System.out.print(s); } else{ System.out.print("Wrong Format"); } break; case 2: int n=sc.nextInt(); if(date.checkInputValidity()&&n>0) { DateUtil date2; date2 = date.getPreviousNDays(n); String s1 = date2.showDate(); System.out.print(s1); break; } else { System.out.print("Wrong Format"); } case 3: DateUtil date3=new DateUtil(sc.nextInt(),sc.nextInt(),sc.nextInt()); if(date.checkInputValidity()&&date3.checkInputValidity()) { int x= date.getDaysofDates(date3); System.out.print(x); } else{ System.out.print("Wrong Format"); } break; default: System.out.print("Wrong Format"); } } } class DateUtil{ private Day day=new Day(); DateUtil(){} DateUtil(int y,int m,int d){ this.day.getMonth().getYear().setValue(y); this.day.getMonth().setValue(m); this.day.setValue(d); } Day getDay(){ return day; } void setDay(Day d){ day=d; } boolean checkInputValidity(){ if(day.getMonth().getYear().validate()&& day.getMonth().validate()&&day.validate()){ return true; } return false; } boolean compareDates(DateUtil date){ if(this.day.getMonth().getYear().getValue()> date.day.getMonth().getYear().getValue()){ return true; } else if(this.day.getMonth().getYear().getValue()< date.day.getMonth().getYear().getValue()){ return false; } else{ if(this.day.getMonth().getValue()> date.day.getMonth().getValue()){ return true; } else if(this.day.getMonth().getValue()< date.day.getMonth().getValue()){ return false; } else { if(this.day.getValue()>date.day.getValue()){ return true; } else if(this.day.getValue()<date.day.getValue()){ return false; } } } return false; } boolean equalTwoDates(DateUtil date){ if(this.day.getMonth().getYear().getValue()== date.day.getMonth().getYear().getValue()&& this.day.getMonth().getValue()== date.day.getMonth().getValue()&& this.day.getValue()==date.day.getValue()){ return true; } return false; } String showDate(){ String s=this.day.getMonth().getYear().getValue() +"-"+this.day.getMonth().getValue()+"-"+ this.day.getValue(); return s; } DateUtil getNextNDays(int n){ while(n>0){ day.dayIncrement(); day.resetMin(); n--; } DateUtil date=new DateUtil(day.getMonth().getYear().getValue(), day.getMonth().getValue(),day.getValue()); return date; } DateUtil getPreviousNDays(int n){ while(n>0){ day.dayDecrement(); day.resetMax(); n--; } DateUtil date=new DateUtil(day.getMonth().getYear().getValue(), day.getMonth().getValue(),day.getValue() ); return date; } int getDaysofDates(DateUtil date){ int day1,day2; day1=(this.day.getMonth().getYear().getValue()-1)*365+ operatorDays(this.day.getMonth().getValue())+this.day.getValue(); if(this.day.getMonth().getYear().isLeapYear()&&this.day.getMonth().getValue()>=3) { day1=day1+1; } day1=day1+(this.day.getMonth().getYear().getValue()-1)/4- (this.day.getMonth().getYear().getValue()-1)/100+ (this.day.getMonth().getYear().getValue()-1)/400; day2=(date.day.getMonth().getYear().getValue()-1)*365+ operatorDays(date.day.getMonth().getValue())+date.day.getValue(); if(date.day.getMonth().getYear().isLeapYear()&&date.day.getMonth().getValue()>=3) { day2=day2+1; } day2=day2+(date.day.getMonth().getYear().getValue()-1)/4- (date.day.getMonth().getYear().getValue()-1)/100+ (date.day.getMonth().getYear().getValue()-1)/400; if(this.equalTwoDates(date)){ return 0; } else if(this.compareDates(date)){ return day1-day2; } else { return day2-day1; } } int operatorDays(int month){ int days=0; switch (month){ case 1: days=days; break; case 2: days=days+31; break; case 3: days=days+59; break; case 4: days=days+90; break; case 5: days=days+120; break; case 6: days=days+151; break; case 7: days=days+181; break; case 8: days=days+212; break; case 9: days=days+242; break; case 10: days=days+273; break; case 11: days=days+304; break; case 12: days=days+334; break; } return days; } } class Day{ private int value; private Month month=new Month(); int[] mon_maxnum= new int[]{31,28,31,30,31,30,31,31,30,31,30,31}; Day(){ } Day(int yearValue,int monthValue,int dayValue){ value=dayValue; month.setValue(monthValue); month.getYear().setValue(yearValue); } int getValue(){ return value; } void setValue(int value1){ value=value1; } Month getMonth(){ return month; } void setMonth(Month value){ month=value; } void resetMin(){ if(month.getYear().isLeapYear()&&month.getValue()==2){ if(value==30) { value = 1; month.monthIncrement(); month.resetMin(); } } else if(value==mon_maxnum[month.getValue()-1]+1){ value=1; month.monthIncrement(); month.resetMin(); } } void resetMax(){ if(month.getYear().isLeapYear()&& month.getValue()==3&&value==0){ month.monthDecrement(); month.resetMax(); value=mon_maxnum[month.getValue()-1]+1; } else if(value==0){ month.monthDecrement(); month.resetMax(); value = mon_maxnum[month.getValue()-1]; } } boolean validate(){ if(value>=1&&(value<=mon_maxnum[month.getValue()-1]+1)&&month.getYear().isLeapYear()){ return true; } else if(value>=1&&value<=mon_maxnum[month.getValue()-1]){ return true; } return false; } void dayIncrement() { value++; } void dayDecrement(){ value--; } } class Month{ private Year year=new Year(); private int value; Month(){ } Month(int yearValue,int monthValue){ value=monthValue; year.setValue(yearValue); } int getValue(){ return value; } void setValue(int value1) { value = value1; } Year getYear(){ return year; } void setYear(Year year1){ year=year1; } void resetMin(){ if(value==13) { value = 1; year.yearIncrement(); } } void resetMax(){ if(value==0) { value = 12; year.yearDecrement();; } } boolean validate(){ if(value>=1&&value<=12){ return true; } return false; } void monthIncrement(){ value++; } void monthDecrement(){ value--; } } class Year{ private int value; Year(){ } Year(int value1){ value=value1; } int getValue(){ return value; } void setValue(int value1){ value=value1; } boolean isLeapYear(){ //判断是否闰年 boolean p=false; if((value%4==0&&value%100!=0)||value%400==0){ p=true; } return p; } boolean validate(){ if(value>=1900&&value<=2050){ return true; } return false; } void yearIncrement(){ value++; } void yearDecrement(){ value--; } }题目集5(7-5)日期聚合二源码
import java.util.Scanner; import static java.lang.System.exit; /** * @author:everglow * @data 2021/10/27 22:02 */ public class Main{ public static void main(String[] args) { Scanner sc=new Scanner(System.in); int choice=sc.nextInt(); int year=sc.nextInt(); int month=sc.nextInt(); int day=sc.nextInt(); DateUtil date=new DateUtil(year,month,day); switch (choice){ case 1: int n1=sc.nextInt(); if(date.checkInputValidity()&&n1>=0) { String s3=date.showDate(); DateUtil date1 = new DateUtil(); date1=date.getNextNDays(n1); String s = date1.showDate(); System.out.print(s3+" next "+n1+" days is:"+s); } else{ System.out.print("Wrong Format"); exit(0); } break; case 2: int n=sc.nextInt(); if(date.checkInputValidity()&&n>=0) { String s2=date.showDate(); DateUtil date2; date2 = date.getPreviousNDays(n); String s1 = date2.showDate(); System.out.print(s2+" previous "+n+" days is:"+s1); break; } else { System.out.print("Wrong Format"); exit(0); } case 3: int year1=sc.nextInt(); int month1=sc.nextInt(); int day1=sc.nextInt(); DateUtil date3=new DateUtil(year1,month1,day1); if(date.checkInputValidity()&&date3.checkInputValidity()) { String y=date.showDate(); String z=date3.showDate(); int x= date.getDaysofDates(date3); System.out.print("The days between "+y+" and "+z +" are:"+x); } else{ System.out.print("Wrong Format"); } break; default: System.out.print("Wrong Format"); exit(0); } } } class DateUtil { private Day day = new Day(); private Year year = new Year(); private Month month = new Month(); int[] mon_maxnum = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; DateUtil() { } DateUtil(int y, int m, int d) { this.year.setValue(y); this.month.setValue(m); this.day.setValue(d); } Day getDay() { return day; } void setDay(Day d) { day = d; } boolean checkInputValidity() { if (year.validate() && month.validate() && day.validate(month.getValue(), year.getValue())) { return true; } return false; } boolean compareDates(DateUtil date) { if (this.year.getValue() > date.year.getValue()) { return true; } else if (this.year.getValue() < date.year.getValue()) { return false; } else { if (this.month.getValue() > date.month.getValue()) { return true; } else if (this.month.getValue() < date.month.getValue()) { return false; } else { if (this.day.getValue() > date.day.getValue()) { return true; } else if (this.day.getValue() < date.day.getValue()) { return false; } } } return false; } boolean equalTwoDates(DateUtil date) { if (this.year.getValue() == date.year.getValue() && this.month.getValue() == date.month.getValue() && this.day.getValue() == date.day.getValue()) { return true; } return false; } String showDate() { String s = this.year.getValue() + "-" + this.month.getValue() + "-" + this.day.getValue(); return s; } DateUtil getNextNDays(int n) { if (year.isLeapYear()) { mon_maxnum[1] = 29; } else { mon_maxnum[1] = 28; } while (n > 0) { day.dayIncrement(); if ((day.getValue() == mon_maxnum[month.getValue() - 1] + 1)) { day.setValue(1); month.monthIncrement(); if (month.getValue() == 13) { month.setValue(1); year.yearIncrement(); if (year.isLeapYear()) { mon_maxnum[1] = 29; } else { mon_maxnum[1] = 28; } } } n--; } DateUtil date = new DateUtil(year.getValue(), month.getValue(), day.getValue()); return date; } DateUtil getPreviousNDays(int n) { if (year.isLeapYear()) { mon_maxnum[1] = 29; } else { mon_maxnum[1] = 28; } while (n > 0) { day.dayDecrement(); if ((day.getValue() == 0)) { if (month.getValue() == 1) { day.setValue(mon_maxnum[11]); } else { day.setValue(mon_maxnum[month.getValue() - 2]); } month.monthDecrement(); if (month.getValue() == 0) { month.setValue(12); year.yearDecrement(); if (year.isLeapYear()) { mon_maxnum[1] = 29; } else { mon_maxnum[1] = 28; } } } n--; } DateUtil date = new DateUtil(year.getValue(), month.getValue(), day.getValue() ); return date; } int getDaysofDates(DateUtil date) { int count = 0; if (this.equalTwoDates(date)) { return 0; } else if (this.compareDates(date)) { if (year.isLeapYear()) { mon_maxnum[1] = 29; } else { mon_maxnum[1] = 28; } while (date.year.getValue() != this.year.getValue() || date.month.getValue() != this.month.getValue() || date.day.getValue() != this.day.getValue()) { count++; day.dayDecrement(); if ((day.getValue() == 0)) { if (month.getValue() == 1) { day.setValue(mon_maxnum[11]); } else { day.setValue(mon_maxnum[month.getValue() - 2]); } month.monthDecrement(); if (month.getValue() == 0) { month.setValue(12); year.yearDecrement(); if (year.isLeapYear()) { mon_maxnum[1] = 29; } else { mon_maxnum[1] = 28; } } } } } else { if (date.year.isLeapYear()) { mon_maxnum[1] = 29; } else { mon_maxnum[1] = 28; } while (date.year.getValue() != this.year.getValue() || date.month.getValue() != this.month.getValue() || date.day.getValue() != this.day.getValue()) { count++; date.day.dayDecrement(); if ((date.day.getValue() == 0)) { if (date.month.getValue() == 1) { date.day.setValue(mon_maxnum[11]); } else { date.day.setValue(mon_maxnum[date.month.getValue() - 2]); } date.month.monthDecrement(); if (date.month.getValue() == 0) { date.month.setValue(12); date.year.yearDecrement(); if (date.year.isLeapYear()) { mon_maxnum[1] = 29; } else { mon_maxnum[1] = 28; } } } } } return count; } } class Day { private int value; int[] mon_maxnum = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; Day() { } Day(int dayValue) { value = dayValue; } int getValue() { return value; } void setValue(int value1) { value = value1; } void resetMin(int year, int month) { } void resetMax(int year, int month) { } boolean validate(int month, int year) { if (value >= 1 && (value <= mon_maxnum[month - 1] + 1) && (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))) { return true; } else if (value >= 1 && value <= mon_maxnum[month - 1]) { return true; } return false; } void dayIncrement() { value++; } void dayDecrement() { value--; } } class Month { private int value; Month() { } Month(int monthValue) { value = monthValue; } int getValue() { return value; } void setValue(int value1) { value = value1; } void resetMin() { if (value == 13) { value = 1; } } void resetMax() { if (value == 0) { value = 12; } } boolean validate() { if (value >= 1 && value <= 12) { return true; } return false; } void monthIncrement() { value++; } void monthDecrement() { value--; } } class Year { private int value; Year() { } Year(int value1) { value = value1; } int getValue() { return value; } void setValue(int value1) { value = value1; } boolean isLeapYear() { //判断是否闰年 boolean p = false; if ((value % 4 == 0 && value % 100 != 0) || value % 400 == 0) { p = true; } return p; } boolean validate() { if (value >= 1820 && value <= 2020) { return true; } return false; } void yearIncrement() { value++; } void yearDecrement() { value--; } }度量:(方法和类)
日期聚合一复杂度:
Method CogC ev(G) iv(G) v(G) fourthpta.DateUtil.DateUtil() 0 1 1 1 fourthpta.DateUtil.DateUtil(int,int,int) 0 1 1 1 fourthpta.DateUtil.checkInputValidity() 2 2 3 4 fourthpta.DateUtil.compareDates(DateUtil) 11 7 6 7 fourthpta.DateUtil.equalTwoDates(DateUtil) 2 2 3 4 fourthpta.DateUtil.getDay() 0 1 1 1 fourthpta.DateUtil.getDaysofDates(DateUtil) 7 3 4 7 fourthpta.DateUtil.getNextNDays(int) 1 1 2 2 fourthpta.DateUtil.getPreviousNDays(int) 1 1 2 2 fourthpta.DateUtil.operatorDays(int) 1 1 1 13 fourthpta.DateUtil.setDay(Day) 0 1 1 1 fourthpta.DateUtil.showDate() 0 1 1 1 fourthpta.Day.Day() 0 1 1 1 fourthpta.Day.Day(int,int,int) 0 1 1 1 fourthpta.Day.dayDecrement() 0 1 1 1 fourthpta.Day.dayIncrement() 0 1 1 1 fourthpta.Day.getMonth() 0 1 1 1 fourthpta.Day.getValue() 0 1 1 1 fourthpta.Day.resetMax() 3 1 5 5 fourthpta.Day.resetMin() 5 1 5 5 fourthpta.Day.setMonth(Month) 0 1 1 1 fourthpta.Day.setValue(int) 0 1 1 1 fourthpta.Day.validate() 4 3 5 6 fourthpta.Month.Month() 0 1 1 1 fourthpta.Month.Month(int,int) 0 1 1 1 fourthpta.Month.getValue() 0 1 1 1 fourthpta.Month.getYear() 0 1 1 1 fourthpta.Month.monthDecrement() 0 1 1 1 fourthpta.Month.monthIncrement() 0 1 1 1 fourthpta.Month.resetMax() 1 1 2 2 fourthpta.Month.resetMin() 1 1 2 2 fourthpta.Month.setValue(int) 0 1 1 1 fourthpta.Month.setYear(Year) 0 1 1 1 fourthpta.Month.validate() 2 2 1 3 fourthpta.Second.main(String[]) 12 1 7 9 fourthpta.Year.Year() 0 1 1 1 fourthpta.Year.Year(int) 0 1 1 1 fourthpta.Year.getValue() 0 1 1 1 fourthpta.Year.isLeapYear() 3 1 1 4 fourthpta.Year.setValue(int) 0 1 1 1 fourthpta.Year.validate() 2 2 1 3 fourthpta.Year.yearDecrement() 0 1 1 1 fourthpta.Year.yearIncrement() 0 1 1 1 Class OCavg OCmax WMC fourthpta.DateUtil 3.17 13 38 fourthpta.Day 1.64 4 18 fourthpta.Month 1.27 2 14 fourthpta.Second 8 8 8 fourthpta.Year 1.25 2 10 日期聚合二复杂度:
Method CogC ev(G) iv(G) v(G) fifth.DateUtil.DateUtil() 0 1 1 1 fifth.DateUtil.DateUtil(int,int,int) 0 1 1 1 fifth.DateUtil.checkInputValidity() 2 2 3 4 fifth.DateUtil.compareDates(DateUtil) 11 7 6 7 fifth.DateUtil.equalTwoDates(DateUtil) 2 2 3 4 fifth.DateUtil.getDay() 0 1 1 1 fifth.DateUtil.getDaysofDates(DateUtil) 51 2 15 19 fifth.DateUtil.getNextNDays(int) 13 1 4 6 fifth.DateUtil.getPreviousNDays(int) 17 1 5 7 fifth.DateUtil.setDay(Day) 0 1 1 1 fifth.DateUtil.showDate() 0 1 1 1 fifth.Day.Day() 0 1 1 1 fifth.Day.Day(int) 0 1 1 1 fifth.Day.dayDecrement() 0 1 1 1 fifth.Day.dayIncrement() 0 1 1 1 fifth.Day.getValue() 0 1 1 1 fifth.Day.resetMax(int,int) 0 1 1 1 fifth.Day.resetMin(int,int) 0 1 1 1 fifth.Day.setValue(int) 0 1 1 1 fifth.Day.validate(int,int) 6 3 1 8 fifth.First.main(String[]) 13 1 8 10 fifth.Month.Month() 0 1 1 1 fifth.Month.Month(int) 0 1 1 1 fifth.Month.getValue() 0 1 1 1 fifth.Month.monthDecrement() 0 1 1 1 fifth.Month.monthIncrement() 0 1 1 1 fifth.Month.resetMax() 1 1 1 2 fifth.Month.resetMin() 1 1 1 2 fifth.Month.setValue(int) 0 1 1 1 fifth.Month.validate() 2 2 1 3 fifth.Year.Year() 0 1 1 1 fifth.Year.Year(int) 0 1 1 1 fifth.Year.getValue() 0 1 1 1 fifth.Year.isLeapYear() 3 1 1 4 fifth.Year.setValue(int) 0 1 1 1 fifth.Year.validate() 2 2 1 3 fifth.Year.yearDecrement() 0 1 1 1 fifth.Year.yearIncrement() 0 1 1 1 Class OCavg OCmax WMC fifth.DateUtil 4 15 44 fifth.Day 1.22 3 11 fifth.First 8 8 8 fifth.Month 1.33 2 12 fifth.Year 1.25 2 10 UML类图:
日期聚合一类图:

日期聚合二类图:

设计和分析:
这俩题题目需求都一样(求下n天,求前n天,求俩个日期相差的天数),差异比较大的地方是类的设计上面,日期聚合一是DateUtil类中有Day类,Day类中有Month类,Month类中有Year类,像是分别用一个类聚合另一个类,实现类似“链条“的结构;日期聚合二是DateUtil类中既有Day类,又有Month类,还有Year类。这是俩种不同的类的设计方式,并且都属于类的聚合。
我们分析圈复杂度,日期聚合一与日期聚合二相比较,Main类的圈复杂度是一样的,而细分到各个类的话,则跟每个类的设计有关系,日期聚合一,环环相扣,所以日期聚合一的年月日类的圈复杂度是逐渐增加的,但是Dateutil类的圈复杂度也没有日期聚合二的圈复杂度高,反观日期聚合二,由于它是Dateutil类圈起年月日三个类,故它的Dateutil类相比较与日期聚合一会大得多,但是它的年月日三个类圈复杂度几乎一样。
结合类图与复杂度分析,我们可以得出二者的优劣:
日期聚合一:优点:类与类之间环环相扣,关系紧密,便于计算。
缺点:类与类关系过于紧密,要是程序出现Bug的话,大部分代码都需要修改。
日期聚合二:优点:逻辑清楚,年月日类之间没有关系,符合“不要和陌生人说话”的面向对象编程理念,便于修改和增删内容。
缺点:类之间的关系太弱,如果需要完成计算等功能,需要添加大幅的代码在Dateutil类中,不便于编写。
-
题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)
这三个题目都是有关图形继承,主要运用到了JAVA特性(封装、继承、接口、多态等)
7-3图形继承源码
import java.math.*; import java.util.Scanner; /** * @author:everglow * @data 2021/10/22 20:47 */ public class Main{ public static void main(String[] args) { Scanner sc=new Scanner(System.in); int choice= sc.nextInt(); switch (choice){ case 1: double s4=sc.nextDouble(); if(s4>0) { Circle c=new Circle(); c.setRadius(s4); System.out.print(String.format("Circle's area:%.2f", c.getArea())); } else { System.out.print("Wrong Format"); } break; case 2: double s=sc.nextDouble(); double s1=sc.nextDouble(); if(s>0&&s1>0) { Rectangle r=new Rectangle(); r.setWidth(s); r.setLength(s1); System.out.print(String.format("Rectangle's area:%.2f", r.getArea())); } else { System.out.print("Wrong Format"); } break; case 3: double s2=sc.nextDouble(); if(s2>0) { Ball b=new Ball(); b.setRadius(s2); System.out.println(String.format("Ball's surface area:%.2f", b.getArea())); System.out.print(String.format("Ball's volume:%.2f", b.getVolume())); } else { System.out.print("Wrong Format"); } break; case 4: double q=sc.nextDouble(); double w=sc.nextDouble(); double e=sc.nextDouble(); if(q>0&&w>0&&e>0) { Box x=new Box(); x.setWidth(q); x.setLength(w); x.setHeight(e); System.out.println(String.format("Box's surface area:%.2f", x.getArea())); System.out.print(String.format("Box's volume:%.2f", x.getVolume())); } else { System.out.print("Wrong Format"); } break; default: System.out.print("Wrong Format"); break; } } } class Shape{ Shape(){ System.out.println("Constructing Shape"); } double getArea(){ return 0.0; } } class Circle extends Shape{ private double radius; Circle(){ System.out.println("Constructing Circle"); } @Override double getArea(){ return Math.PI*radius*radius; } double getRadius(){ return radius; } void setRadius(double c){ radius=c; } } class Rectangle extends Shape{ private double width; private double length; Rectangle(){ System.out.println("Constructing Rectangle"); } @Override double getArea(){ return width*length; } double getWidth(){ return width; } double getLength(){ return length; } void setWidth(double a){ width=a; } void setLength(double b){ length=b; } } class Ball extends Circle{ Ball(){ System.out.println("Constructing Ball"); } @Override double getArea(){ return 4*Math.PI*getRadius()*getRadius(); } double getVolume(){ return 4.0/3*Math.PI*Math.pow(getRadius(),3); } } class Box extends Rectangle{ private double height; Box(){ System.out.println("Constructing Box"); } double getHeight(){ return height; } void setHeight(double s){ height=s; } @Override double getArea(){ return (getLength()*getWidth()+getLength()*height +getWidth()*height)*2; } double getVolume(){ return getLength()*getWidth()*height; } }7-5图形继承与多态源码
import java.util.ArrayList; import java.util.Scanner; import java.util.TreeMap; /** * @author:everglow * @data 2021/11/6 18:06 */ public class Main{ Scanner sc=new Scanner(System.in); ArrayList<Shape> tests=new ArrayList<Shape>(); public static void main(String[] args) { Main test=new Main(); test.input(); test.show_messages(); } public void input(){ int a=sc.nextInt(); int b=sc.nextInt(); int c=sc.nextInt(); if(a<0||b<0||c<0){ System.out.println("Wrong Format"); System.exit(0); } Circle[] circles=new Circle[a]; Rectangle[] rectangles=new Rectangle[b]; Triangle[] triangles=new Triangle[c]; for(int i=0;i<a;i++){ circles[i]=new Circle(sc.nextDouble()); if(!circles[i].validate()){ System.out.println("Wrong Format"); System.exit(0); } tests.add(circles[i]); } for(int i=0;i<b;i++){ rectangles[i]=new Rectangle(sc.nextDouble(),sc.nextDouble()); if(!rectangles[i].validate()){ System.out.println("Wrong Format"); System.exit(0); } tests.add(rectangles[i]); } for(int i=0;i<c;i++){ triangles[i]=new Triangle(sc.nextDouble(),sc.nextDouble(),sc.nextDouble()); if(!triangles[i].validate()){ System.out.println("Wrong Format"); System.exit(0); } tests.add(triangles[i]); } } public void show_messages() { double sum = 0; System.out.print("Original area:"); System.out.print("\n"); for (int i = 0; i < tests.size(); i++){ sum = sum + tests.get(i).getArea(); System.out.printf("%.2f ", tests.get(i).getArea()); } System.out.print("\n"); System.out.printf("Sum of area:%.2f\n", sum); for (int i = 0; i < tests.size() - 1; i++) { for (int j = 1; j < tests.size(); j++) { if (tests.get(j-1).getArea()>tests.get(j).getArea()) { Shape temp = tests.get(j); tests.set(j,tests.get(j-1)); tests.set(j-1,temp); } } } System.out.println("Sorted area:"); for (int i = 0; i < tests.size(); i++) { System.out.printf("%.2f ", tests.get(i).getArea()); } System.out.print("\n"); System.out.printf("Sum of area:%.2f", sum); } } abstract class Shape{ abstract double getArea(); abstract boolean validate(); } class Circle extends Shape{ private double radius; Circle(double radius){ this.radius=radius; } double getArea(){ return Math.PI*radius*radius; } boolean validate(){ if(radius>0){ return true; } return false; } } class Rectangle extends Shape{ private double width; private double length; Rectangle(double width,double length){ this.width=width; this.length=length; } double getArea(){ return width*length; } boolean validate(){ if(width>=0&&length>=0){ return true; } return false; } } class Triangle extends Shape{ private double side1; private double side2; private double side3; Triangle(double side1,double side2,double side3){ this.side1=side1; this.side2=side2; this.side3=side3; } double getArea(){ double p=(side1+side2+side3)/2; return Math.sqrt(p*(p-side1)*(p-side2)*(p-side3)); } boolean validate(){ if(side1>=0&&side2>=0&&side3>=0&&side1+side2>side3 &&side3+side2>side1 &&side1+side3>side2){ return true; } return false; } }7-6实现图形接口及多态性源码
import java.util.Scanner; /** * @author:everglow * @data 2021/11/7 12:10 */ public class Main{ public static void main(String[] args) { Scanner sc=new Scanner(System.in); Circle1 circle=new Circle1(sc.nextDouble()); Rectangle1 rectangle=new Rectangle1(sc.nextDouble(),sc.nextDouble()); if(!circle.validate()|| !rectangle.validate()){ System.out.println("Wrong Format"); System.exit(0); } System.out.printf("%.2f\n",circle.getArea()); System.out.printf("%.2f\n",rectangle.getArea()); } } interface GetArea{ double getArea(); } class Circle1 implements GetArea{ private double radius; Circle1(double radius){ this.radius=radius; } Circle1(){ } public double getArea(){ return Math.PI*radius*radius; } boolean validate(){ if(radius>0){ return true; } return false; } double getRadius(){ return radius; } void setRadius(double radius){ this.radius=radius; } } class Rectangle1 implements GetArea{ private double width; private double length; Rectangle1(){} Rectangle1(double width,double length){ this.width=width; this.length=length; } public double getArea(){ return width*length; } boolean validate(){ if(width>0&&length>0){ return true; } return false; } void setLength(double length){ this.length=length; } void setWidth(double width){ this.width=width; } double getWidth(){ return width; } double getLength(){ return length; } }度量:(方法和类)
7-3图形继承的复杂度
Method CogC ev(G) iv(G) v(G) fourthpta.Ball.Ball() 0 1 1 1 fourthpta.Ball.getArea() 0 1 1 1 fourthpta.Ball.getVolume() 0 1 1 1 fourthpta.Box.Box() 0 1 1 1 fourthpta.Box.getArea() 0 1 1 1 fourthpta.Box.getHeight() 0 1 1 1 fourthpta.Box.getVolume() 0 1 1 1 fourthpta.Box.setHeight(double) 0 1 1 1 fourthpta.Circle.Circle() 0 1 1 1 fourthpta.Circle.getArea() 0 1 1 1 fourthpta.Circle.getRadius() 0 1 1 1 fourthpta.Circle.setRadius(double) 0 1 1 1 fourthpta.Rectangle.Rectangle() 0 1 1 1 fourthpta.Rectangle.getArea() 0 1 1 1 fourthpta.Rectangle.getLength() 0 1 1 1 fourthpta.Rectangle.getWidth() 0 1 1 1 fourthpta.Rectangle.setLength(double) 0 1 1 1 fourthpta.Rectangle.setWidth(double) 0 1 1 1 fourthpta.Shape.Shape() 0 1 1 1 fourthpta.Shape.getArea() 0 1 1 1 fourthpta.Third.main(String[]) 15 1 5 12 Class OCavg OCmax WMC fourthpta.Ball 1 1 3 fourthpta.Box 1 1 5 fourthpta.Circle 1 1 4 fourthpta.Rectangle 1 1 6 fourthpta.Shape 1 1 2 fourthpta.Third 10 10 10 7-5图形继承与多态的复杂度
Method CogC ev(G) iv(G) v(G) sixthpta.Circle.Circle(double) 0 1 1 1 sixthpta.Circle.getArea() 0 1 1 1 sixthpta.Circle.validate() 1 2 1 2 sixthpta.Fifth.input() 11 1 8 10 sixthpta.Fifth.main(String[]) 0 1 1 1 sixthpta.Fifth.show_messages() 12 5 8 8 sixthpta.Rectangle.Rectangle(double,double) 0 1 1 1 sixthpta.Rectangle.getArea() 0 1 1 1 sixthpta.Rectangle.validate() 2 2 1 3 sixthpta.Triangle.Triangle(double,double,double) 0 1 1 1 sixthpta.Triangle.getArea() 0 1 1 1 sixthpta.Triangle.validate() 2 2 1 7 Class OCavg OCmax WMC sixthpta.Circle 1.33 2 4 sixthpta.Fifth 5.67 8 17 sixthpta.Rectangle 1.33 2 4 sixthpta.Shape n/a n/a 0 sixthpta.Triangle 1.33 2 4 7-6实现图形接口及多态性的复杂度
Method CogC ev(G) iv(G) v(G) sixthpta.Circle1.Circle1() 0 1 1 1 sixthpta.Circle1.Circle1(double) 0 1 1 1 sixthpta.Circle1.getArea() 0 1 1 1 sixthpta.Circle1.getRadius() 0 1 1 1 sixthpta.Circle1.setRadius(double) 0 1 1 1 sixthpta.Circle1.validate() 1 2 1 2 sixthpta.Rectangle1.Rectangle1() 0 1 1 1 sixthpta.Rectangle1.Rectangle1(double,double) 0 1 1 1 sixthpta.Rectangle1.getArea() 0 1 1 1 sixthpta.Rectangle1.getLength() 0 1 1 1 sixthpta.Rectangle1.getWidth() 0 1 1 1 sixthpta.Rectangle1.setLength(double) 0 1 1 1 sixthpta.Rectangle1.setWidth(double) 0 1 1 1 sixthpta.Rectangle1.validate() 2 2 1 3 sixthpta.Sixth.main(String[]) 2 1 3 3 Class OCavg OCmax WMC sixthpta.Circle1 1.17 2 7 sixthpta.Rectangle1 1.12 2 9 sixthpta.Sixth 2 2 2 UML类图:
7-5图形继承与多态类图:

7-6图形接口及多态类图:

设计与分析:
这三个题目内容差不多,都是跟图形相关的需求,求面积之类的。通过分析类图,不难看出三个题目类的设计各有不同,7-3图形继承就是简单的子类继承父类,然后子类重写父类的方法,再进行求面积;7-5图形继承与多态中父类是一个抽象类,使用多态让子类继承父类,然后子类重写父类的方法,调用时会调用子类方法而不是调用父类方法;7-6图形接口与多态则是把求面积作为一个接口,让图形类使用这个接口再重写方法,进而完成求面积的需求。三个题目让我们认识并熟悉了JAVA的特性(继承,多态,接口)。
但是我们在真正实现题目需求时需要考虑清楚什么时候应该使用继承,继承虽然实现了代码复用,减少了代码书写量,便于修改,但是它打破了封装,当父类的实现发生改变时又要对相应的子类做出改变。什么时候需要使用接口,接口可以实现类似多继承的功能,但是接口加入一个方法后,所有使用过接口的类都必须加入这个方法并重写。什么时候需要使用多态,没有继承就没有多态,使用多态有可替换性、灵活性、简化性等特点。这些都是我们编写程序需要考虑的细节。
-
正则表达式技术的分析总结
分析与总结:
这三次题目集一共出现了5道有关正则表达式的应用的题目,其中第三次题目集的三道题目较为简单,前俩次题目集的2道题目较为复杂,复杂的原因在于需要处理判断的数据不是简简单单的位数问题,还有相应的符号问题和分隔符。正则表达式一般用于字符校验和特殊需求,通过写正则表达式可以省略很多不必要的步骤,节省很多代码,提高代码的整洁度。我是通过菜鸟教程上的JAVA正则表达式和正则表达式在线测试进行学习的正则表达式,

然后对照着题目达到自己想要的结果。我不是很清楚题目集为什么安排正则表达式的顺序是从难到易,第一个题目和第二个题目要处理的数据比后俩个复杂得多,但是却安排在了前面。下面是我写的正则表达式:
"(((([1-9])|([1-9][0-9])|([1-9][0-9]{2})|([1-9][0-9]{3})/((([13578]|1[02])/([1-9]|[12][0-9]|3[01]))|(([469]|11)/([1-9]|[12][0-9]|30))|(2/([1-9]|[1][0-9]|2[0-8])))))|(((([1-9][0-9])(0[48]|[2468][048]|[13579][26]))|(([48]|[2468][048]|[3579][26])00))/2/29)) ((([02468])|(1[02468])|(2[02])):00)"
"^[1-9][0-9]{4,14}"
"\\w{4}"
"^2020([1][1-7]|7[1-3]|81|61)([0-3][1-9]|40)"
第一个正则表达式相较于其他的正则表达式会复杂很多,但是从头到尾去分析的话,也不会特别麻烦,总而言之就是当你需要处理的数据比较庞大时,你所需要使用的正则表达式也会相应的变复杂。在我看来正则表达式是一个很好的工具,用作校验数据的手段,可以用于很多类型的文本处理,如匹配,搜索,提取和分析结构化内容,为我们之后编写程序如需要校验数据也可以首先考虑是否可以用正则表达式解决问题。
-
题目集5(7-4)中Java集合框架应用的分析总结
7-4源码
import java.util.*;
/**
* @author:everglow
* @data 2021/10/28 13:58
*/
public class Main{
public static void main(String[] args) {
int a;
Func test=new Func();
test.fun1();
test.input();
test.fun2();
test.show_map();
Show_Data data=new Show_Data();
data.compute();
data.show_data(test.mp);
data.setFl2ag(3);
a=data.getfl2();
test.setB("ss");
StringBuilder y=test.getX();
String x=test.getB();
}
}
class Show_Data{
int fl2ag;
Show_Data(){
}
void show_data(Map<String,Integer> mp){
String map1 = String.valueOf(mp);
String[] map3 = map1.replace("{", "").replace("}", "").split(", ");
for (int i = 0; i < map3.length; i++) {
String[] map4 = map3[i].split("=");
if (!map4[1].equals("0")) {
System.out.println(map4[1] + "\t" + map4[0]);
}
}
}
void compute(){
int fl2=0;
for(int i=10000;i>0;i--){
if((i%100!=0&&i%4==0)||i%400==0){
fl2++;
}
}
}
int getfl2(){
return fl2ag;
}
void setFl2ag(int fl2ag){
this.fl2ag=fl2ag;
}
}
class Func{
Scanner sc=new Scanner(System.in);
String important="abstract assert boolean break byte case catch char class const continue default do " +
" double else enum extends final finally float for goto if implements import instanceof int " +
"interface long native new package private protected public return strictfp short static super " +
"switch synchronized this throw throws transient try void volatile while true false null";
String []ims=important.split(" ");
String []special = {"\\$","_","int\\(\\)","boolean\\(\\)","double\\(\\)","float\\(\\)","byte\\(\\)","long\\(\\)","short\\(\\)","\\*"};
Map<String, Integer> mp=new TreeMap<String, Integer>();
StringBuilder x=new StringBuilder();
String b;
Func(){
}
String getB(){
return b;
}
void setB(String b){
this.b=b;
}
StringBuilder getX(){
return x;
}
void setX(StringBuilder s){
x=s;
}
void fun1(){
for(String i:ims) {
mp.put(i,0);
}
}
void input(){
String s;
s=sc.nextLine();
while(!(s.trim()).equals("exit")){
x.append(s.replaceAll("//.*"," ")
.replaceAll("\".*?\""," " ));
s=sc.nextLine();
}
}
void fun2(){
int flag=0;
b=x.toString().replaceAll("/\\*\\s*.*?\\s*\\*/"," ");
if(b.length()==0){
System.out.print("Wrong Format");
System.exit(0);
}
b=b.replaceAll("\\p{P}"," ");
String[] temp=b.split("\\s+");
for(String e:temp){
if(mp.containsKey(e)){
mp.put(e,mp.get(e)+1);
flag=1;
}
}
if(flag==0){
System.exit(0);
}
}
void show_map() {
String map1 = String.valueOf(mp);
String[] map3 = map1.replace("{", "").replace("}", "").split(", ");
for (int i = 0; i < map3.length; i++) {
String[] map4 = map3[i].split("=");
}
}
}
度量:(方法与类)
| Method | CogC | ev(G) | iv(G) | v(G) |
|---|---|---|---|---|
| fifth.Func.Func() | 0 | 1 | 1 | 1 |
| fifth.Func.fun1() | 1 | 1 | 2 | 2 |
| fifth.Func.fun2() | 5 | 1 | 5 | 5 |
| fifth.Func.getB() | 0 | 1 | 1 | 1 |
| fifth.Func.getX() | 0 | 1 | 1 | 1 |
| fifth.Func.input() | 1 | 1 | 2 | 2 |
| fifth.Func.setB(String) | 0 | 1 | 1 | 1 |
| fifth.Func.setX(StringBuilder) | 0 | 1 | 1 | 1 |
| fifth.Func.show_map() | 1 | 1 | 2 | 2 |
| fifth.Second.main(String[]) | 0 | 1 | 1 | 1 |
| fifth.Show_Data.Show_Data() | 0 | 1 | 1 | 1 |
| fifth.Show_Data.compute() | 5 | 1 | 1 | 5 |
| fifth.Show_Data.getfl2() | 0 | 1 | 1 | 1 |
| fifth.Show_Data.setFl2ag(int) | 0 | 1 | 1 | 1 |
| fifth.Show_Data.show_data(Map<String, Integer>) | 3 | 1 | 3 | 3 |
| Class | OCavg | OCmax | WMC | |
| fifth.Func | 1.78 | 5 | 16 | |
| fifth.Second | 1 | 1 | 1 | |
| fifth.Show_Data | 1.8 | 3 | 9 |
设计与分析:
这题题目内容是查询关键字出现次数,JAVA中一共有53个关键字,查询一段话里面一共出现了几次相关的关键字,这是我们需要去解决的。这题目用到了JAVA的集合框架应用,这是我们之前没有使用过的,JAVA集合框架大致可以分为俩类:Clolection和Map。在这次题目中,我们使用到的是Map类,使用方法就是用Map类存储关键字,使每一个关键字对应一个值,这个值就是我们所需要输出的出现次数,通过把关键字存储在Map里,再将需要处理的字符串用正则表达式分割成一个个小块,再用map里的方法find查找该小块是否包含关键字,如果包含,所在关键字的值加一,遍历结束后,将关键字次数大于0的关键字连同次数按照关键字首字母大小排序后输出即可。这一题难点我个人觉得主要在Map的使用和正则表达式的使用。
这题就是JAVA集合框架的典型应用。如果我们需要保存一个可以动态增长的数据(在编译时无法确定具体的数量),java的集合类就是一个很好的设计方案。Map保存的是"键值对",就像一个小型数据库,我们可以通过"键"找到该键对应的"值"。
三. 踩坑心得
- 第一个踩坑的是水文数据校验及其处理,由于这个题目难度相较而言较大,而自己又没有仔细的去学习正则表达式,导致自己在做这题的时候所花费的时间比较久,按照类图写完自己的程序之后还需要想数据之间是怎么传输的,也可能是作业指导书有些地方描述的不够详细,导致自己一时没有理清各个类,然后就是用正则表达式去判断截取数据比较所花费的时间比较多,但是这些上网查找资料,参考学习后都可以解决。
- 踩的第二个坑是日期聚合的问题,问题是在日期聚合一出现的,当时就一直都有一个测试点过不去,测试点是“日期越界”,但是我自己测试的数据都能够正常使用,不会出现错误,我询问同学同学也没有发现问题是在哪里,但是在我做日期聚合二的时候,我发现了问题所在,应该是数据运算的地方出了问题,于是我修改了日期聚合二的算法,相较于日期聚合一,改进了一下算法,日期聚合二提交就没有上述的错误。

- 第三个坑也是在日期聚合上出的问题,问题是日期聚合二的运行超时问题,当时测试数据放上去是没有问题,我最初是以为算法有问题,因为我的程序如果用最大整型数据去测试,程序需要1-2秒才会出结果,我觉得可能是这里的问题,后面发现修改算法后测试点还是依然报错,最后自己Debug实在找不出问题,我就去问了一个同学,他查看了我的代码后发现是我的代码在对n天的时候,每次n-1都会进行一次闰年判断,这样就增加了运行时间,这可能也是测试点测试的地方,我通过修改代码,让年份加一时才判断闰年,再提交,这个问题得以解决。

- 最后一个问题是比较容易出的问题,每次感觉都会出现一俩次,就是输出格式的问题,一是题目提示不够详细,二是自己不够细心,导致每次过格式错误的测试点都需要花费一些时间,但是这种问题,只要自己不断去分析,对照测试数据,基本上都可以解决。
四. 改进建议
- 针对正则表达式的话,我觉得我还是需要不断去学习,不断去掌握,然后用较少的代码去完成自己想达到的效果,而不是一长条一大串,学习的路径就是去菜鸟教程或者是B站看讲解视频。
- 对具体的题目改进的话,我觉得对类的设计方面我可以有自己的理解,就算题目给出了它的UML类图,我也可以根据自己的理解适当修改,然后就算要写程序之前要先理清各个模块之间的关系,不要到最后程序写完了不知道程序应该怎么跑起来,然后就算类的设计尽量要使用到JAVA的特性(封装性,接口,多态,继承等)。
五. 总结
- 这三次题目集让我学习到了很多有关JAVA的特性,让我进一步接触了JAVA是什么类型的语言,面向对象,虽然在做题目的过程中花费了自己的很多时间,但是自己从中收获到了很多知识,类的特性,类的设计,正则表达式,MAP等等,我觉得这是一次很有意义的学习。
- 我需要学习的点倒是还挺多的,首先就是要去精进正则表达式,然后就是深刻理解JAVA的三大特性,并在自己的程序需要时用上JAVA特性,而不是仅仅停留在脑子里的概念,总之就是不断努力吧。
- 我觉得题目顺序有挺大的问题,第三次题目集的正则表达式明显比前俩次题目集的正则表达式简单很多,但是它却作为最后来让我们做,我个人建议是题目循序渐进,由易到难慢慢来,对正则表达式的训练我觉得也应该如此,这样做下来的体验就是第一次题目集蒙圈做,做完也没有特别懂,也没有什么成就感,然后第三次题目集很轻松就做完正则方面的题目,所以我建议是题目区分难度,由易到难逐渐发布比较合适。

浙公网安备 33010602011771号