OO第二次大作业——来自小白星球总结
一、前言
第四次题目集:
1.题目量为三题:7-1 水文数据校验及处理 ,7-2 日期问题面对对象设计(聚合一), 7-3 图形继承。
2.知识点:(1)字符串String方法,例如:equals()、trim()、split()、maches()等进行字符串的分割、比较、匹配等操作;(2)使用private进行数据域的封装;(3)计算日期使用聚合进行类设计,即在一个类中有另一个类的实体引用(类中的类);(4)实现图形类的继承,并在子类中重写父类的方法;(5)使用正则表达式进行字符串的匹配划分处理。
3.难度:总体难度不是很大,水文校验处理需要使用较多正则表达式的匹配,相对难一些,其他两题从算法上看相对简单。
第五次题目集:
1.题目量为四题:7-5 日期问题面对对象设计(聚合二),7-4 统计Java程序中关键词的出现次数,7-2 合并两个有序数组为新的有序数组,7-3 对整型数据排序。
2.知识点:(1)在日期问题上使用聚合(已提供类图);(2)采用StringBuilder对字符串进行操作,可直接改变字符串本身,而不是生成新的对象;(3)使用String字符串的replace()和replaceAll()方法;(4)Pattern类用于编译正则表达式后创建一个匹配模式,Matcher类使用Pattern实例提供的模式信息对正则表达式进行匹配。Pattern.compile()和Pattern.matcher()方法;(5)将两个数组排序输出(选择排序);(6)使用插入排序、选择排序、冒泡排序对数组排序。
3.难度:数组排序相对简单,日期问题在测试点上较第一次题目集更细,统计关键字有两个测试点未通过,没找到问题所在。
第六次题目集:
1.题目量为六题:7-1 正则表达式训练-QQ号校验,7-2 字符串训练-字符排序,7-3 正则表达式训练-验证码校验,7-4 正则表达式训练-学号校验,7-5 图形继承与多态,7-6 实现图形接口及多态性。
2.知识点:(1)简单正则表达式校验;(2)类的继承多态使用;(3)图形接口及多态。
3.难度:相对前两次题目集都更简单。
二、设计与分析
①题目集4(7-2)、题目集5(7-5)两种日期类聚合设计的优劣比较。
图为题目集4(7-2)源码在SourceMonitor中的分析图:


图为题目集5(7-5)源码在SourceMonitor中的分析图:


分析:两次题目的圈复杂度都偏高。
两次题目类图比较分析:
题目集4(7-2)类图:

题目集5(7-5)类图:

题目提示类图:

分析:两次类图其实差别应该不大,主要是算法上的健壮性进一步进行了修改,在做类聚合一的时候考虑的还算周全,和聚合二题目给的类图已经很接近。
部分设计源码:
1 //Year类 2 class Year{ 3 int value; 4 //默认构造方法 5 public Year(){ 6 } 7 //带参构造方法 8 public Year(int value){ 9 this.value=value; 10 } 11 //getter 12 public int getValue(){ 13 return value; 14 } 15 //setter 16 public void setValue(int value){ 17 this.value=value; 18 } 19 //判断year是否为闰年 20 public boolean isLeapYear(){ 21 return ((value % 4 == 0 && value % 100 != 0) || value % 400 == 0); 22 } 23 //效验数据合法性 24 public boolean validate(){ 25 return value <= 2020 && value >= 1820; 26 } 27 //年份加一 28 public void yearIncrement(){ 29 value=value+1; 30 } 31 //年份减一 32 public void yearReduction(){ 33 value=value-1; 34 } 35 } 36 //Month类 37 class Month{ 38 int value; 39 Year year; 40 //默认构造方法 41 public Month(){ 42 } 43 //带参构造方法 44 public Month(int yearValue,int monthValue){ 45 this.year=new Year(yearValue); 46 this.value=monthValue; 47 } 48 //value getter 49 public int getValue(){ 50 return value; 51 } 52 // value setter 53 public void setValue(int value){ 54 this.value=value; 55 } 56 //Year getter 57 public Year getYear(){ 58 return year; 59 } 60 //Year setter 61 public void setYear(Year year){ 62 this.year=year; 63 } 64 //日期复位(1) 65 public void resetMin(){ 66 value=1; 67 } 68 //月份设置为12 69 public void resetMax(){ 70 value=12; 71 } 72 //效验数据合法性 73 public boolean validate(){ 74 return value >= 1 && value <= 12; 75 } 76 //月份加一 77 public void dayIncrement(){ 78 value=value+1; 79 } 80 //月份减一 81 public void dayReduction(){ 82 value=value-1; 83 } 84 } 85 //Day类 86 class Day{ 87 int value; 88 Month month; 89 int[] a ={31,28,31,30,31,30,31,31,30,31,30,31}; 90 //默认构造方法 91 public Day(){ 92 } 93 //带参构造方法 94 public Day(int yearValue,int monthValue,int dayValue){ 95 this.month=new Month(yearValue,monthValue); 96 this.value=dayValue; 97 } 98 //getter 99 public int getValue(){ 100 return value; 101 } 102 public Month getMonth(){ 103 return month; 104 } 105 //setter 106 public void setValue(int value){ 107 this.value=value; 108 } 109 public void setMonth(Month value){ 110 this.month=value; 111 } 112 //日期复位(1) 113 public void resetMin(){ 114 value=1; 115 } 116 //日期设为该月最大值 117 public void resetMax(){ 118 value=a[month.getValue()-1]; 119 } 120 //效验数据合法性 121 public boolean validate(){ 122 if(this.getMonth().getYear().isLeapYear()) 123 a[1]=29; 124 if(this.getMonth().validate()) { 125 return value >= 1 && value <= a[month.getValue() - 1]; 126 } 127 else{ 128 return false; 129 } 130 } 131 //日期加一 132 public void dayIncrement() { 133 value=value+1; 134 } 135 //日期减一 136 public void dayReduction() { 137 value=value-1; 138 } 139 }
②题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)。
1. 题目集4(7-3)图形继承 在SourceMonitor中的分析图和类图:



分析:继承是面对对象语法的三大特征之一,通过继承,子类获得了父类的成员变量和方法,通过关键字extends可以申明一个类是从另外一个类中继承而来的。例如:
1 class 父类{ 2 ....... //成员变量、成员方法 3 } 4 class 子类 extends 父类{ 5 ....... //类体 6 }
注: 1.子类不能选择性继承父类;
2.Java不支持多重继承,但一个类可以实现多个接口,从而克服单继承的缺点;
3.构造方法不会被子类继承,但可以从子类中调用父类的构造方法。
重写:子类中的一个实例方法具有与父类中的一个实例方法具有相同的签名(指名称、参数个数、类型)和返回值时,称子类中的方法重写了父类中的方法。
使用super调用父类中重写的方法以及访问父类中被隐藏的字段。
源码:
1 package PTA4; 2 import java.util.Scanner; 3 4 public class Main3 { 5 public static void main(String[] args){ 6 Scanner input = new Scanner(System.in); 7 int option = input.nextInt(); 8 if(option == 1){ //圆 9 double circle = input.nextDouble(); 10 if(circle >= 0) { 11 Circle c = new Circle(); 12 c.setRadius(circle); 13 System.out.printf("Circle's area:%.2f", c.getArea()); 14 } 15 else{ 16 System.out.print("Wrong Format"); 17 } 18 System.exit(0); 19 } 20 else if(option == 2){ //矩形 21 double width = input.nextDouble(); 22 double length = input.nextDouble(); 23 if(width>=0 && length>=0) { 24 Rectangle r = new Rectangle(); 25 r.setWidth(width); 26 r.setLength(length); 27 System.out.printf("Rectangle's area:%.2f",r.getArea()); 28 } 29 else{ 30 System.out.print("Wrong Format"); 31 } 32 System.exit(0); 33 } 34 else { 35 if(option == 3){ //球 36 double circle = input.nextDouble(); 37 if(circle>=0) { 38 Ball b = new Ball(); 39 b.setRadius(circle); 40 System.out.printf("Ball's surface area:%.2f\n",b.getArea()); 41 System.out.printf("Ball's volume:%.2f",b.getVolume()); 42 } 43 else{ 44 System.out.print("Wrong Format"); 45 } 46 } 47 else { 48 if(option == 4){ //立方体 49 double width = input.nextDouble() ; 50 double length = input.nextDouble() ; 51 double height = input.nextDouble(); 52 if(length>=0 && width>=0 && height>=0) { 53 Box box = new Box(); 54 box.setWidth(width); 55 box.setLength(length); 56 box.setHeight(height); 57 System.out.printf("Box's surface area:%.2f\n",box.getArea()); 58 System.out.printf("Box's volume:%.2f",box.getVolume()); 59 } 60 else{ 61 System.out.print("Wrong Format"); 62 } 63 } 64 else{ 65 System.out.print("Wrong Format"); 66 } 67 } 68 System.exit(0); 69 } 70 } 71 } 72 //图形面积类 73 class Shape{ 74 public Shape(){ //无参构造 75 System.out.println("Constructing Shape"); 76 } 77 public double getArea(){ 78 return 0.0; 79 } 80 } 81 //圆面积类 82 class Circle extends Shape{ 83 private double radius; 84 //构造方法 85 public Circle() { 86 System.out.println("Constructing Circle"); 87 } 88 //setter 89 public void setRadius(double radius){ 90 this.radius = radius; 91 } 92 //getter 93 public double getRadius() { 94 return radius; 95 } 96 //计算面积 97 public double getArea(){ 98 return Math.PI*radius*radius; 99 } 100 } 101 //矩形面积类 102 class Rectangle extends Shape{ 103 private double width; 104 private double length; 105 //构造方法 106 public Rectangle(){ 107 System.out.println("Constructing Rectangle"); 108 } 109 // width setter 110 public void setWidth(double width){ 111 this.width = width; 112 } 113 //width getter 114 public double getWidth(){ 115 return width; 116 } 117 //length setter 118 public void setLength(double length){ 119 this.length = length; 120 } 121 //width getter 122 public double getLength(){ 123 return length; 124 } 125 //计算面积 126 public double getArea(){ 127 return length*width; 128 } 129 } 130 //球体积类 131 class Ball extends Circle{ 132 //构造方法 133 public Ball(){ 134 System.out.println("Constructing Ball"); 135 } 136 //求球的表面积 137 public double getArea(){ 138 return 4*Math.PI*super.getRadius()*super.getRadius(); 139 } 140 //求球的体积 141 public double getVolume(){ 142 return 4*Math.PI*super.getRadius()*super.getRadius()*super.getRadius()/3; 143 } 144 } 145 //立方体体积类 146 class Box extends Rectangle{ 147 private double height; 148 //构造方法 149 public Box(){ 150 System.out.println("Constructing Box"); 151 } 152 //setter 153 public void setHeight(double height){ 154 this.height = height; 155 } 156 //getter 157 public double getHeight(){ 158 return height; 159 } 160 //求立方体的表面积 161 public double getArea(){ 162 return 2*(super.getLength()*super.getWidth() + super.getLength()*height + super.getWidth()*height); 163 } 164 //求立方体的体积 165 public double getVolume(){ 166 return super.getLength()*super.getWidth()*height; 167 } 168 }
2.题目集六7-5 图形继承与多态 在SourceMonitor中的分析图和类图:



分析: 多态在使用父类类型的引用abstract抽象,只能调用父类中定义的方法和变量,变量不能被重写,重写只针对方法。覆盖时动态绑定,重载是静态绑定,用instanceof操作符测试一个对象是否是一个对象的实例,instanceof返回值是true或false。
注:方法看右侧,属性看左侧。先访问父类的构造方法再访问子类的构造方法。
源码:
1 package PTA6; 2 import java.util.ArrayList; 3 import java.util.Collections; 4 import java.util.Scanner; 5 public class Main5{ 6 public static void main(String[] args) { 7 ArrayList<Double> sumarea = new ArrayList<>(); //面积表 8 Scanner input = new Scanner(System.in); 9 int m = input.nextInt(); //m表示圆的数量 10 int n = input.nextInt(); //n表示长方形的数量 11 int p = input.nextInt(); //t表示三角形的数量 12 // int p = m+2*n+3*t; //一共要输入的边长,按顺序存入数组中 13 if(m>=0 && n>=0 && p>=0) { //数量输入合法 14 Circle c[] = new Circle[m]; 15 Rectangle r[] = new Rectangle[n]; 16 Triangle t[] = new Triangle[p]; 17 18 //圆面积 19 for (int i = 0; i < m; i++) { 20 c[i] = new Circle(input.nextDouble()); 21 if (!c[i].validate()) { 22 System.out.print("Wrong Format"); 23 System.exit(0); 24 } 25 sumarea.add(c[i].getArea()); 26 } 27 //矩形面积 28 for(int j = 0; j < n; j++){ 29 r[j] = new Rectangle(input.nextDouble(), input.nextDouble()); 30 if(!r[j].validate()){ 31 System.out.print("Wrong Format"); 32 System.exit(0); 33 } 34 sumarea.add(r[j].getArea()); 35 } 36 //三角形面积 37 for(int k = 0; k < p; k++){ 38 t[k] = new Triangle(input.nextDouble(), input.nextDouble(), input.nextDouble()); 39 if(!t[k].validate()){ 40 System.out.print("Wrong Format"); 41 System.exit(0); 42 } 43 sumarea.add(t[k].getArea()); 44 } 45 Show show = new Show(); 46 show.showAll(sumarea); 47 show.showAddsum(sumarea); 48 show.showSort(sumarea); 49 show.showAddsum1(sumarea); 50 } 51 else{ 52 System.out.print("Wrong Format"); 53 } 54 } 55 } 56 //图形父类 57 abstract class Shape{ 58 public Shape(){ //无参构造 59 } 60 public double getArea(){ 61 return 0.0; 62 } 63 public boolean validate(){ 64 return true; 65 } 66 } 67 class Show{ 68 //输出表中面积 69 public void showAll(ArrayList<Double> sumarea){ 70 System.out.println("Original area:"); 71 for(double i: sumarea){ 72 System.out.printf("%.2f ",i); 73 } 74 System.out.println(); 75 } 76 //对面积求和 77 public void showAddsum(ArrayList<Double> sumarea){ 78 System.out.print("Sum of area:"); 79 double sum = 0; 80 for(double i: sumarea){ 81 sum +=i; 82 } 83 System.out.printf("%.2f",sum); 84 System.out.println(); 85 } 86 //对面积排序 87 public void showSort(ArrayList<Double> sumarea){ 88 System.out.println("Sorted area:"); 89 Collections.sort(sumarea); 90 for(double i: sumarea){ 91 System.out.printf("%.2f ",i); 92 } 93 System.out.println(); 94 } 95 //对面积求和 96 public void showAddsum1(ArrayList<Double> sumarea){ 97 System.out.print("Sum of area:"); 98 double sum = 0; 99 for(double i: sumarea){ 100 sum +=i; 101 } 102 System.out.printf("%.2f",sum); 103 } 104 } 105 //圆面积类 106 class Circle extends Shape { 107 private double radius; 108 //无参构造方法 109 public Circle() { 110 } 111 //带参构造方法 112 public Circle(double radius){ 113 this.radius = radius; 114 } 115 //setter 116 public void setRadius(double radius){ 117 this.radius = radius; 118 } 119 //getter 120 public double getRadius() { 121 return radius; 122 } 123 //判断是否合法 124 @Override 125 public boolean validate(){ 126 if(radius > 0) 127 return true; 128 else 129 return false; 130 } 131 //计算面积 132 @Override 133 public double getArea(){ 134 return Math.PI*radius*radius; 135 } 136 } 137 //矩形面积类 138 class Rectangle extends Shape { 139 private double width; 140 private double length; 141 //构造方法 142 public Rectangle(){ 143 } 144 //带参构造函数 145 public Rectangle(double width, double length){ 146 this.width = width; 147 this.length = length; 148 } 149 // width setter 150 public void setWidth(double width){ 151 this.width = width; 152 } 153 //width getter 154 public double getWidth(){ 155 return width; 156 } 157 //length setter 158 public void setLength(double length){ 159 this.length = length; 160 } 161 //width getter 162 public double getLength(){ 163 return length; 164 } 165 //判断是否合法 166 @Override 167 public boolean validate(){ 168 if(width>0 && length>0) 169 return true; 170 else 171 return false; 172 } 173 //计算面积 174 @Override 175 public double getArea(){ 176 return length*width; 177 } 178 } 179 //三角形面积类 180 class Triangle extends Shape{ 181 private double side1; 182 private double side2; 183 private double side3; 184 public Triangle(){ //无参构造 185 } 186 //带参构造 187 public Triangle(double side1, double side2, double side3){ 188 this.side1 = side1; 189 this.side2 = side2; 190 this.side3 = side3; 191 } 192 //side1 getter 193 public double getSide1() { 194 return side1; 195 } 196 //side1 setter 197 public void setSide1(double side1){ 198 this.side1 = side1; 199 } 200 //side2 getter 201 public double getSide2() { 202 return side2; 203 } 204 //side2 setter 205 public void setSide2(double side2) { 206 this.side2 = side2; 207 } 208 //side3 getter 209 public double getSide3() { 210 return side3; 211 } 212 //side3 setter 213 public void setSide3(double side3) { 214 this.side3 = side3; 215 } 216 //判断是否合法,三边大于零且任意两边之和大于第三边 217 @Override 218 public boolean validate(){ 219 if(side1<side2){ 220 double temp = side1; 221 side1 = side2; 222 side2 = temp; 223 } 224 if(side1<side3){ 225 double temp = side1; 226 side1 = side3; 227 side3 = temp; 228 } 229 if(side1>0&&side2>0&&side3>0&&(side2+side3)>side1) 230 return true; 231 else 232 return false; 233 } 234 //计算面积(海伦公式) 235 @Override 236 public double getArea(){ 237 double p = (side1+side2+side3)/2; 238 return Math.sqrt(p*(p-side1)*(p-side2)*(p-side3)); 239 } 240 241 }
3.题目集合7-6 实现图形接口及多态性 在SourceMonitor中的分析图和类图:



分析:抽象方法是指没有方法体的实体,同时抽象方法还必须使用关键字abstract做修饰,而拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。例如:
1 abstract class A{ 2 public void fun(){ //普通方法 3 System.out.print("存在方法体的方法"); 4 } 5 public abstract void print(); //抽象方法,没有方法体,有abstract做修饰 6 }
注:抽象类的使用原则:
1.抽象类必须为public或者protected(因为如果private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为Public;
2.抽象类方法不能直接实例化,需要依靠子类采用向上转型的方式处理;
3.抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
4.子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类中没有实现父类抽象的方法,则必须将该子类也定义为abstract类)。
源码:
1 package PTA6; 2 import java.util.Scanner; 3 public class Main6 { 4 public static void main(String[] args){ 5 Scanner input = new Scanner(System.in); 6 double radius = input.nextDouble(); //输入圆半径 7 double width = input.nextDouble(); //输入宽 8 double length = input.nextDouble(); //输入高 9 Circle1 c = new Circle1(radius); 10 Rectangle1 r = new Rectangle1(width,length); 11 if(c.validate()&&r.validate()) { //输入合法 12 GetArea m = new Circle1(radius); 13 System.out.printf("%.2f",m.getArea()); 14 System.out.println(); 15 GetArea n = new Rectangle1(width,length); 16 System.out.printf("%.2f",n.getArea()); 17 } 18 else{ 19 System.out.print("Wrong Format"); 20 } 21 } 22 } 23 //圆面积类 24 class Circle1 implements GetArea{ 25 private double radius; 26 //无参构造方法 27 public Circle1() { 28 } 29 //带参构造方法 30 public Circle1(double radius){ 31 this.radius = radius; 32 } 33 //setter 34 public void setRadius(double radius){ 35 this.radius = radius; 36 } 37 //getter 38 public double getRadius() { 39 return radius; 40 } 41 //判断是否合法 42 public boolean validate(){ 43 if(radius > 0) 44 return true; 45 else 46 return false; 47 } 48 //计算面积 49 public double getArea(){ 50 return Math.PI*radius*radius; 51 } 52 } 53 //矩形面积类 54 class Rectangle1 implements GetArea{ 55 private double width; 56 private double length; 57 //构造方法 58 public Rectangle1(){ 59 } 60 //带参构造函数 61 public Rectangle1(double width, double length){ 62 this.width = width; 63 this.length = length; 64 } 65 // width setter 66 public void setWidth(double width){ 67 this.width = width; 68 } 69 //width getter 70 public double getWidth(){ 71 return width; 72 } 73 //length setter 74 public void setLength(double length){ 75 this.length = length; 76 } 77 //width getter 78 public double getLength(){ 79 return length; 80 } 81 //判断是否合法 82 public boolean validate(){ 83 if(width>0 && length>0) 84 return true; 85 else 86 return false; 87 } 88 //计算面积 89 public double getArea(){ 90 return length*width; 91 } 92 } 93 //面积接口类 94 interface GetArea { 95 public abstract double getArea(); 96 }
③对三次题目集中用到的正则表达式技术的分析总结。
1.去除多余空格
1 s.trim()
2.时间合法性检验,测量时间:格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],“月”与“日”为一位数时之前不加“0”,日期与时间之间有一个空格,“时”与“分”之间采用冒号分隔(英文半角),“时”为一位数时之前不加“0”,“分”始终保持两位,且始终为“00”。注意:“时”数必须是24小时进制中的偶数值。
1 String time="(?:(?( [1-9]| 1[0-9]| 2[0-3]| 00):00))"; 2 String regex1="(?:((?:([1-9]([0-9]{0,3}))/((?:(([1-9]|(1[0-2]))/(?:([1-9]|([1-2][0-8])|19))))|(?:(([13578])|([1][02])(/31)))|(?:(([13-9]|1[02])/(29|30)))))(?:(?:( [02468]| 1[02468]| 2[02]|):00))))"; 3 String regex2="(?:((?:([48]|[2468][048]|[13579][26]))|((?:(([1-9]([0-9]?))?:(0[48]|[2468][048]|[13579][26])))|(?:([48]|[2468][048]|[13579][26])00))/2/29)(?:(?:( [02468]| 1[02468]| 2[02]|):00)))"; 4 String regexend=regex1+"|"+regex2;
3.目标水位、实际水位、流量:均为实型数,取值范围为[1,1000), 小数点后保留1-3位小数或无小数(也无小数点)。
1 String water ="(?:(?:(([1-9]([0-9]{0,2})))(?:((.[0-9]{1,3})?))))"
4.目标开度、实际开度:实型数,取值范围为[1,10),必须保留2位小数,两个开度之间用“/”分隔。
1 String hot="(?:(([1-9])(?:(.[0-9]{2}))))";
5.判断输入是否以 ‘ | ’分割五段。
1 return this.getData().trim().split("\\|").length == 5;
6.以空格替代注释‘//’和‘""’的内容。
1 return line.replaceAll("//.*", " ").replaceAll("\".*\"", " ");
7.以空格替代注释‘/* */’里的内容。
1 return word.toString().replaceAll("/\\*\\s*.*\\s*\\*/", " ");
8.以空格替代’{ }’。
1 return arry.replace("{","").replace("}","");
9.QQ号校验,要求必须是 5-15 位,0 不能开头,必须都是数字。
1 return str.matches("[1-9][0-9]{4,14}");
10.验证码校验,由四位数字或者字母(包括大小写)组成的字符串。
1 return str.matches("[a-zA-Z-0-9]{4}");
11.学号校验,对软件学院2020级同学学号进行校验,学号共八位,规则如下:
- 1、2位:入学年份后两位,例如20年
- 3、4位:学院代码,软件学院代码为20
- 5位:方向代码,例如1为软件工程,7为物联网
- 6位:班级序号
- 7、8位:学号(序号)
1 return s.matches("2020((1[1-7])|(61)|(7[1-3])|(8[1-2]))(0[1-9]|1[0-9]|2[0-9]|3[0-9]|40)");
总结: 1.常用元字符需要牢记:






2.常用的校验:
- 验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"1"~"12"。
- 验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。
- 验证用户密码:"^[a-zA-Z]"w{5,17}$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
④题目集5(7-4)中Java集合框架应用的分析总结。
在题目实现中,并未用到集合框架。查询相关资料,对集合框架做了一个初步了解。
什么是集合框架?
Java集合类主要由两个根接口Collection和Map派生出来的,Collection派生出了三个子接口:List、Set、Queue(Java5新增的队列),因此Java集合大致也可分成List、Set、Queue、Map四种接口体系,(注意:Map不是Collection的子接口)。
集合体系中常用的实现类,分别是ArrayList、LinkedList、ArrayQueue、HashSet、TreeSet、HashMap、TreeMap等实现类。
ArrayList是一个动态数组,也是我们最常用的集合,是List类的典型实现。它允许任何符合规则的元素插入甚至包括null。每一个ArrayList都有一个初始容量(10),该容量代表了数组的大小。随着容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。所以如果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。ArrayList擅长于随机访问元,同时ArrayList是非同步的。
Map接口采用键值对Map<K,V>的存储方式,保存具有映射关系的数据,因此,Map集合里保存两组值,一组值用于保存Map里的key,另外一组值用于保存Map里的value,key和value可以是任意引用类型的数据。key值不允许重复,可以为null。如果添加key-value对时Map中已经有重复的key,则新添加的value会覆盖该key原来对应的value。常用实现类有HashMap、LinkedHashMap、TreeMap等。
三、踩坑心得
1.题目集5中7-5 日期问题面对对象设计(聚合二),测试点提示为整型数最大值/最小值测试,开始以为输入需要使用BigInterger进行改进,后来发现是算法错误。
2.在求下n天的整型数最大值测试的测试点花费了较长时间。原因是:如果前一年是闰年,2月天数被置成29,而在后面算法中并没有更改过来,因此造成一个bug,测试了很多的数据才发现该错误,测试源码如下:
1 //其下n天 2 public DateUtil getNextDays(int n) { 3 int[] a = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 4 int sum; //当前年份剩余值 5 if (this.getDay().getMonth().getYear().isLeapYear()) { //如果是闰年 6 a[2] = 29; 7 } 8 int y = this.getDay().getMonth().getYear().getValue(); //y为年份 9 int m = this.getDay().getMonth().getValue(); //m为月份 10 int d = this.getDay().getValue(); //d为日期 11 sum = a[m] - d; 12 //计算当前年份剩余天数 13 if(m != 12){ 14 for (int i = m + 1; i <= 12; i++) { 15 sum = sum + a[i]; 16 } 17 } 18 //sum = sum + a[m] - d; 19 //在同一年 20 if (sum > n) { 21 //在同一月 22 if (n + d <= a[m]) { 23 d = d + n; 24 }//if 25 //不在同一月 26 else { 27 n = n - (a[m] - d); //除去当月后的剩余天数 28 int i = m + 1; 29 while (n > a[i]) { 30 n = n - a[i]; 31 i++; 32 } 33 m = i; 34 d = n; 35 }//else 36 }//if 37 //不在同一年 38 else { 39 n = n - sum; 40 int i = y + 1; 41 int days = 365; 42 if (new Year(i).isLeapYear()) { //如果是闰年 43 days = 366; 44 } 45 // int k = n; 46 while (n - days > 0) { 47 i++; 48 n = n - days; 49 days = 365; 50 if (new Year(i).isLeapYear()) { //判断当前i+1是否是闰年 51 days = 366; 52 } 53 }//while 54 y = i; //当前年份 55 //如果是一月 56 if (n <= a[1]) { 57 m = 1; 58 }//if 59 //如果不是一月 60 else { 61 if (new Year(y).isLeapYear()) { //当前年份是不是闰年 62 a[2] = 29; 63 }//if 64 else{ 65 a[2]= 28; 66 } 67 int j = 1; //从二月开始判断他有几个月 68 // n = n-31; //减去一月的天数 69 // int t = n; 70 while (n - a[j] > 0) { 71 n = n - a[j]; 72 j++; 73 }//while 74 // y = i; 75 m = j; 76 }//else 77 d = n; 78 }//else 79 return new DateUtil(d, m, y); 80 }
3.题目集4 7-1 水文数据校验及处理中,应该是测试点不够严谨,输出格式显示为结尾无空行,我在编写程序的时候还一度不知道如何处理,在调试过程中找到基础错误后提交就直接通过了。


四、改进建议
1.对于7-5 日期问题面向对象设计(聚合),可以对类进行一个封装,设计类图中很多方法并未使用到,没有完全达到一个封装与聚合的效果,还可以改进。
2.对于7-4 统计Java程序中关键字的出现次数,还存在两个测试点未通过, 在编程中,并未使用到集合框架进行关键字的输出排序,还有待改进。

3.正则表达式校验题目,掌握的还不够熟练,一些表达式还可以进行简化。
五、总结
相比于第一次大作业,在JAVA编程思想上有了较大的转变,写程序开始以设计类和方法的思想去思考问题,而不是以面对过程的思想,经过这三周的题目集训练。对整个面对对象JAVA有了一个更加深入的了解。初步掌握了面对对象的三大特性:封装、继承和多态。以及初步接触了接口。封装就是把描述一个对象的属性和行为封装在一个类中,使用private修饰的属性将不被公开或直接被其它对象访问,其他类只能通过调用get和set方法来引用;继承就是在一个已经存在的类基础上定义和实现一个新类,该类可以通过extends来实现对父类的继承,在子类中可以加入新的内容或者通过重写父类的方法,使用super不仅可以引用父类的构造方法,也可以引用父类的方法;多态就是在声明时使用父类,在实现或调用具体的子类,在不修改程序代码就可以改变程序运行所绑定的具体代码,让程序可以选择多个运行状态;接口interface 就是从几个类中派生出一个子类,继承它们所有的属性和方法,其解决了JAVA不支持多重继承的缺点,注:接口是一种特殊的抽象类,只包含常量和方法的定义,而没有变量和方法和实现。然后就是在正则表达式的验证上还不太熟练。

浙公网安备 33010602011771号