OOP题目集第二次总结(4~6)
一.前言
4~6题目集,第四次的题目集题量最少,只要三道,但是题目最难,一度难到我怀疑人生。最后向老师反映,题目集5,6难度下降,但是增加了题目量。三次题目集考察了较多的知识点,正则表达式,类的聚合,保留小数格式可采用String.format,图形继承设计的思路与技术运用(封装、继承、多态、接口等)。
题目集4总共只要三道题,第一题为水文数据校验及处理,第二题为日期问题面向对象设计(聚合一),最后一题为图形继承。
题目集5总共有五道题,前面三道题目较为基础,第四题为统计Java中出现的关键次次数,这道题最难,第五题为日期问题面向对象设计(聚合二)。
题目集6总共有六道题,1、3、4为正则表达式校验,2为字符串排序,5为图形继承与多态,6为实现图形接口与多态性。
二.设计与分析
①.题目集4(7-2)、题目集5(7-5)两种日期类聚合设计的优劣比较
题目集4(7-2)


题目集5(7-5)


两道题的复杂程度大致相同,基本上是一样的,但是两种类的聚合设计却有很大的不同之处。题目集4(7-2)是互相连接的,year聚合到month,month聚合到day,day聚合到Dateutil,而题目集5(7-5)是year ,month,day全都聚合到Dateutil中,没有前面那道题的传递聚合。相比于题目集4(7-2),题目集5(7-5)的聚合在数据的处理上会更加的简单简便,它只需要将数据全部聚合大Dateutil中。题目集4(7-2)需要在各个类中写入方法,而在题目集5(7-5)中可以将大部分方法全部只写入一个类中,就是Dateutil中,会更加直观,清晰。
②题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)
题目集4(7-3)构造shape类,在shape类中写入获得图形面积的方法,通过子类继承父类,即类Circle类继承自Shape,类Rectangle继承自Shape,类Ball继承自Circle,类Box继承自Rectangle,子类从父类继承各个属性,并且重写父类提供的的方法,完成了对各种基本图形的属性和方法构造。


class Shape{
public Shape() {
System.out.println("Constructing Shape");
}
public double getArea() {
return 0.0;
}
}
class Circle extends Shape{
public Circle() {
System.out.println("Constructing Circle");
}
private double r;
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
public double getArea() {
double s=0;
s=Math.PI*r*r;
return s;
}
}
class Rectangle extends Shape{
public Rectangle() {
System.out.println("Constructing Rectangle");
}
private double width;
private double length;
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getArea() {
double s1=0;
s1=length*width;
return s1;
}
}
class Ball extends Circle{
public Ball() {
System.out.println("Constructing Ball");
}
public double getArea() {
double s2=0;
s2=4*super.getArea();
return s2;
}
public double getVolume() {
double v=0;
double r1=super.getR();
v=Math.PI*r1*r1*r1*4.0/3.0;
return v;
}
}
class Box extends Rectangle{
public Box() {
System.out.println("Constructing Box");
}
private double height;
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getVolume() {
double v1=0;
v1=height*super.getArea();
return v1;
}
public double getArea() {
double width1=0;
double length1=0;
length1=getLength();
width1=getWidth();
double s3=0;
s3=2*(width1*length1+width1*height+height*length1);
return s3;
}
}
题目集6(7-5、7-6)

这两题分别使用抽象类和接口,同时也用到了继承和封装,继承提供了软件复用功能。若类B继承类A,那么建立类B时只需要再描述与基类(类A)不同的少量特征(数据成员和成员方法)即可。这种做法能减小代码和数据的冗余度,大大增加程序的重用性。抽象类要被子类继承,接口要被类实现。接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。使用interface接口,
接口中的所有成员变量都默认是由public static final修饰的。接口中的所有方法都默认是由public abstract修饰的。接口没有构造方法。构造方法用于创建对象。
实现接口的类中必须提供接口中所有方法的具体实现内容。多个无关的类可以实现同一个接口。一个类可以实现多个无关的接口。与继承关系类似,接口与实现类之间存在多态性。接口也可以继承另一个接口,使用extends关键字。实现接口的类中必须提供接口中所有方法的具体实现内容。多个无关的类可以实现同一个接口。一个类可以实现多个无关的接口。与继承关系类似,接口与实现类之间存在多态性。
这些题目都使用了封装,对数据进行了封装。封装可以方便对数据进行修改,有利于保护数据的完整性。提高了代码的可维护性。
③对三次题目集中用到的正则表达式技术的分析总结
1.题目集4(7-1)水文数据校验与处理。
该题对数据的检测需要使用正则表达式。我首先用二维数组将数据处理,将它们分割在存入二维数组中,最后通过正则表达式进行判断。
但是我最后却没有办法进行数据的计算。

public static boolean validateData(String s) {
return Pattern.matches("(.*)\\\\*|(.*)\\\\*|(.*)\\\\*|(.*)\\\\*|(.*)", date);
}
//数据合法性校验
public static boolean validateMeasureDateTime(String measureDateTime) {
return Pattern.matches("((([1-9]{1}|[1-9][0-9]{1}|[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,1}[0-9]{0,1})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))/2/29)) ([02468]|1[02468]|2[02]):00",measureDateTime);
}
//采集时间合法性校验
public static boolean validateWaterLevel(String waterLevel) {
return Pattern.matches("(([1-9][0-9]{0,2})|(([1-9][0-9]{0,2})(\\.[0-9]{1,3})))", waterLevel );
}
//水位,流量合法性校验
public static boolean validateGateOpening(String gateOpening) {
return Pattern.matches("(([1-9]|[1-9][0])(\\.[0-9]{2}))", gateOpening);
}
//开度合法性校验
2.题目集5(7-4)统计Java程序中关键词出现的次数
该题需要对一段代码统计出的关键字及数量按照关键字升序进行排序输出。在这道题需要我们使用正则表达式进行对注释内容的判断,最后将它们替换成空字符,最后只剩代码内容进行统计
//替换注释内容
Pattern p=Pattern.compile("/\\*(.*)?\\*/");
Matcher m=p.matcher(a);
while(m.find()) {
a=a.replace(m.group()," ");
m=p.matcher(a);
}
//替换字符串内容
p=Pattern.compile("\"(.*?)\"");
m=p.matcher(a);
while(m.find()) {
a=a.replace(m.group()," ");
m=p.matcher(a);
}
3.题目集6(7-1)正则表达式训练-校正QQ号。
该题需要校验qq号的正确性,qq号有5-15位,第一位不能是0,并且全部都为数字
代码如下所示:
public static boolean qq(String s) {
return Pattern.matches("[1-9][0-9]{4,14}", s);
}
4.题目集6(7-3)正则表达式训练-验证码校验
验证码是由四位数字或者字母(包含大小写)组成的字符串。
代码如下所示:
public static boolean qq(String s) {
return Pattern.matches("[0-9]{4}||[a-z]{4}||[A-Z]{4}", s);
}
其实我觉得我的源码是有问题的,它不能判断数字和字母组合在一起的情况,只能判断全为数字,或者全为字母的情况。但是测试点只有一个,最后就很巧的通过了。
5.题目集6(7-4)正则表达式训练-学号校验
要求如下:只针对2020级,其中软件工程专业班级分别为:202011~17、61,物联网工程专业班级为202071~202073,数据科学与大数据专业班级为202081~82,每个班级学号后两位为01~40
代码如下所示:
public static boolean num(String s) {
return Pattern.matches("([2][0][2][0])([1][1-7]{1}||[6][1]||[7][1-3]{1}||[8][1-3]{1})([0][1-9]{1}||[1-3][0-9]||[4][0])", s);
}//数据合法性校验
这道题还是蛮简单的。(嘿嘿。。。)
④题目集5(7-4)中Java集合框架应用的分析总结
题目集5(7-4)为统计Java中出现的关键词
1 import java.util.Comparator; 2 import java.util.Map; 3 import java.util.Scanner; 4 import java.util.TreeMap; 5 import java.util.regex.Matcher; 6 import java.util.regex.Pattern; 7 public class Main { 8 static String []special = {"\\$","_","int\\(\\)","boolean\\(\\)","double\\(\\)","float\\(\\)","byte\\(\\)","long\\(\\)","short\\(\\)","\\*"}; 9 public static String change(String s){ 10 if (s.length()<800) return s; 11 for (String e: special) s = s.replaceAll(e, "SBTIMU"); 12 return s; 13 } 14 public static void main(String[] args) { 15 Scanner input=new Scanner(System.in); 16 String a =null; 17 StringBuilder b=new StringBuilder(); 18 // Map<String, Integer> map=new TreeMap<String, Integer>(Comparator.comparing(String::gethashcode)); 19 Map<String, Integer> map=new TreeMap<String, Integer>((u,v)->{return u.compareTo(v);}); 20 String []key= { "public","abstract","assert","boolean","break","byte","case","catch", 21 "char","class","const","continue","default","do","double","else", 22 "enum","extends","false","final","finally","float", 23 "for","goto","if","implements","import","instanceof", 24 "int","interface","long","native","new","null","package", 25 "private","protected","return","short","static", 26 "strictfp","super","switch","synchronized","this","throw", 27 "throws","transient","true","try","void","volatile","while" 28 }; 29 for(String e:key) map.put(e, 0); 30 while(!(a=input.nextLine().trim()).equals("exit")) { 31 if(a.matches(".*//.*")) continue; 32 b.append(a+" "); 33 } 34 a=b.toString();/*?*/ 35 a=change(a); 36 //替换注释内容 37 Pattern p=Pattern.compile("/\\*(.*)?\\*/"); 38 Matcher m=p.matcher(a); 39 while(m.find()) { 40 a=a.replace(m.group()," "); 41 m=p.matcher(a); 42 } 43 //替换字符串内容 44 p=Pattern.compile("\"(.*?)\""); 45 m=p.matcher(a); 46 while(m.find()) { 47 a=a.replace(m.group()," "); 48 m=p.matcher(a); 49 } 50 if(a.length()==0) {System.out.println("Wrong Format");System.exit(0);} 51 a=a.replaceAll("\\p{P}"," "); 52 String[] s=a.split("\\s+"); 53 int flag=0;//判断是否有关键字 54 for(String e:s) 55 if(map.containsKey(e)) {map.put(e,map.get(e)+1);flag=1;} 56 if(flag==0){System.out.println("Wrong Format");System.exit(0);} 57 map.forEach((e,u)->{if(u!=0)System.out.printf("%d\t%s\n",u,e);}); 58 } 59 }
该题我使用了Map接口,Map是双队集合,用来存储一一映射的一对数据。我使用了TreeMap。因为题目要求对关键词进行排序,而TreeMap能够按照添加的key-value进行排序实现排序的遍历。此时考虑key的自然排序或定制排序。所以我认为使用TreeMap是最合适的。但是这道题有一个垃圾测试点,只能用一种方法强行通过
代码如下所示:
1 static String []special = {"\\$","_","int\\(\\)","boolean\\(\\)","double\\(\\)","float\\(\\)","byte\\(\\)","long\\(\\)","short\\(\\)","\\*"}; 2 public static String change(String s){ 3 if (s.length()<800) return s; 4 for (String e: special) s = s.replaceAll(e, "SBTIMU"); 5 return s; 6 }
三、踩坑心得
1.题目集4(7-2)

算法有错误,在计算日期是否输入错误时,将闰年的2月29号判断成错误输入了。
2.题目集4(7-1)

这道题在数据的计算上出现了bug,我将数据分隔存入了一个二维数组中,在进行计算时,数据并未能成功取出。
3.题目集5(7-4)
该题是统计Java中出现的关键字
最先开始做这道题时,我先将所以单词存入数组中,并然后用if语句进行判断是否为关键字,并统计出现的次数,但是我无法用它进行排序输出,而且有些词并未存入数组中,统计次数时会有少了的。然后我将它改为Map接口进行,TreeMap,才顺利解决。
4.题目集6(7-5)
根据题目要求的排序要求,我使用list进行排序,使用list.add()进行数据的存储,但是在进行数据的输出时,会将[ ]符号输出,最后我实在是无法解决,改成使用冒泡排序法进行排序
四、改进意见
题目难度有难有易,如果题目很难的话,可以让题目量少一点,简单的话可以让题目量多一点。
对于自己所写的代码的话,我觉得自己的代码还是很垃圾的垃圾代码,复杂度依旧很高,而且有一部分的题目对于它的逻辑性是有问题的,虽然所有测试点可以通过,但是仔细去思考,可以发现有些特殊的情况按照我的代码根本不可能通过。
题目集6(7-3)
验证码是由四位数字或者字母(包含大小写)组成的字符串。
代码如下所示:
public static boolean qq(String s) {
return Pattern.matches("[0-9]{4}||[a-z]{4}||[A-Z]{4}", s);
}
其实我觉得我的源码是有问题的,它不能判断数字和字母组合在一起的情况,只能判断全为数字,或者全为字母的情况。但是测试点只有一个,最后就很巧的通过了。
改进想法:
return Pattern.matches("^{0-9A-Za-z}{4}$",s);
五、总结
从这三次的题目集,我学会了正则表达式,类的聚合,抽象类,保留小数格式可采用String.format,图形继承设计的思路与技术运用(封装、继承、多态、接口等)以及Java的集合框架。
Aggregation(聚合关系) 是关联关系的一种,是强的关联关系。聚合关系是整体和个体的关系。普通关联关系的两个类处于同一层次上,而聚合关系的两个类处于不同的层次,一个是整体,一个是部分。同时,是一种弱的“拥有”关系。体现的是A对象可以包含B对象,但B对象不是A对象的组成部分。具体表现为,如果A由B聚合成,表现为A包含有B的全局对象,但是B对象可以不在A创建的时刻创建。
接口中的所有成员变量都默认是由public static final修饰的。接口中的所有方法都默认是由public abstract修饰的。接口没有构造方法。构造方法用于创建对象。
实现接口的类中必须提供接口中所有方法的具体实现内容。多个无关的类可以实现同一个接口。一个类可以实现多个无关的接口。与继承关系类似,接口与实现类之间存在多态性。接口也可以继承另一个接口,使用extends关键字。实现接口的类中必须提供接口中所有方法的具体实现内容。多个无关的类可以实现同一个接口。一个类可以实现多个无关的接口。与继承关系类似,接口与实现类之间存在多态性。
Java的集合框架分为Collection接口和Map接口。
Collection接口分为List接口和Set接口。
List接口存储有序的、可重复的数据。ArrayList、LinkedList、Vector。
Set接口存储无序的、不可重复的数据。HashSet、LinkedSet、TreeSet。
Map是双队集合,用来存储一一映射的一对数据。HashMap、LinkedHashMap(HashMap子类)、TreeMap、Hashtable、Properties(Hashtable子类)。
最后,对这种上课的模式 感觉还可以,老师也会对我们的情况做出调整,上次和老师说题目太难,老师立马修改了难度。

浙公网安备 33010602011771号