OO第二次博客作业总结
20201124-熊彩虹
一、分析与总结
1、第四次作业
(1)作业总体总结:
这一次的作业题量不大,只有三题,除了第一道题有一定难度之外,另外两道题一个是日期的迭代,还有一个是形状面积的迭代的难度都不是特别困难(但是还是遇到了一定的问题和疑惑的)。第一道题是水文数据校验及处理,在这里考察的重点仍然是正则表达式(非常重要),还有CheckData、DealData两个类的作用以及对需求分析。日期的迭代在之前的练习中已经写过两次了,都用的是不同的方法,这一次更侧重于聚集的考察。第三道题是面积形状的迭代,这是我们最熟悉的一个题目了,但是这次题目也有的许多升级和改动。这次的题目的重点是锻炼我们对继承的理解与使用,区分父类子类二者的用法,以及对代码的复用,和抽象类的使用和作用的理解。
(2)题目分析
1)7-2分析:这一题与题目集五中的7-5一起分析。
圈复杂度及类图:
7-2:最大圈复杂度为11



7-5:最大圈复杂度是15



优劣点:从上面两张图可以看出二者的最大圈复杂度的大小,7-2的最大圈复杂度要稍小于7-5的圈复杂度。在7-2和7-5中两道题使用的都是聚合。在7-2中,dateUtil中引用Day类,Day类中又引用Month类,在Month类中引用Year类,这样的缺点是一旦前面的类无法使用后,会导致后面的类也没法使用,而在7-5中Year,Month,Day都放在DateUtil中,则不存在这样的问题,例如即使Day类无法使用,Month,Year类仍然可以照常使用。这样会导致7-2的代码的耦合性高于7-5,并且我们写代码的原则就是耦合性越低越好。二者都还有一个共同的缺点就是运行的时间过长,会导致运行超时。在7-5时体现的更加明显,当使用for循环处理天数增加或减少问题的时候,如果碰到了int型最大值就会运行超时,可以采用将for循环中的int型改成long型,或者改善算法不使用for循环进行操作。比如在计算下n天的时候,可以直接按年份的天数相加,等到最后一年的时候再使用for循环,这样可以大大减少程序运行的时间。
2)7-3分析
圈复杂度及类图:



最大复杂度度为9,在类中所有的属性均使用了private私有型,在此题中,使用的是让Circle,Ball,Box,Rectangle继承自Shape,Shape是父类,Circle,Ball,Box,Rectangle是子类,其中Shape类还是一个抽象的类,其中有getArea()方法,在子类中分别重写该方法。
3)7-1分析
这一题的重点是正则表达式的匹配还有分组。经过前三次的作业,对正则表达式已经有一点熟悉了,而这次则是对数字和日期的匹配进行练习。在编写代码的过程中,首先遇到了对小数点后几位的匹配出现问题,因为有的是一位小数,有的是两位或者是三位,没有办法去确定。后来我通过 对数字进行 ( ?) 加上问号的处理,这样位数就可以出现0次或多次。首先是对输入的数据一行一行的读入处理,对输入的数据判断之后就是对数据进行分组,在这里我采用的是group()的方法,将一行中的数据分为五部分:测量时间、目标水位、实际水位、开度(包含目标开度和实际开度,以“/” 分隔)、流量,然后挨个对数据进行处理并且记录下行与列。
(3)踩坑心得
在测试天数的时候,天数少的时候没问题不会出错,但是一旦天数变大就会存在差值。在debug之后发现是闰年2月份的问题,在之前的代码中我是设定了天数数组,初始时二月天数是28天,在检测日期是否合法时如果是闰年就将2月份改为29天。所以这个问题就出现了,我在代码中只在最开始用户输入数据的时候检测了日期的合法性,所以年份发生改变后并没有再次检测合法性并对2月份天数进行操作。于是我在计算下n天和前n天的循环中加上了检测日期合法性的方法,于是在每一次天数改变后都会去判断日期合法和对2月份操作。
但是这个方法很快又出现了新的问题,一旦我将2月份天数改变为29后,此后的2月份天数就一直是29。于是对代码有进行了改进,在原有代码只有将28天改为29天的方法,增加一个从29天到28天的方法。
(4)改进建议
在7-2和7-5中都存在一个很明显的问题,代码运行时间过长导致运行超时。这个是由于for循环导致的,如果数据小也行没什么问题,但是一个数据过大,比如int的最大值,就会运行时间过长。可以试着将for循环进行改进。比如可以将天数按年分,若该年是闰年就天数加或减366,平年加或减365,当剩余天数小于366的时候再使用for循环,这样就可以稍微减少一些运行时间。还有一个改善运行超时的方法就是将for循环中的 int i = 0 改为 long i = 0.
2、第五次作业
(1)作业总体总结:
这一次的题目集中,题目量和难度适中,只是7-4统计关键字出现的次数稍微有些困难。作业考察了我们对字符串,数组的操作和处理等,在7-3中还考察了我们对数组的三种排序,其中选择排序和冒泡排序是我们曾经就已经接触过的排序方法,最后一个插入排序是在这一次作业中才开始接触的。7-4是统计Java程序中关键词的出现次数并且进行排序,这道题仍然需要使用到正则表达式以及我还使用了group()方法和List接口。最后是7-5,是对日期的处理,在第四次作业中我已经和7-3一起分析过了它们两道题的优劣势,所以在这里就不再赘述了。
(2)题目分析
1)7-4分析:
圈复杂度以及类图


最大复杂度为19(还是有点稍高了!),圈复杂度过高是由于if-else,switch,循环语句过多,导致分支过多。在查询资料之外知道了有以下几个基础的方法去降低圈复杂度。
1、采用三元表达式
1 c = (condition) ? a : b;
2、合并条件表达式
1 boolean flag = a || b || c ; 2 if (flag) {
3 …
4 }
3、去掉没有必要的else
1 if (false) 2 { 3 return; 4 } 5 false;
另外,这道题中,各类的属性采用的均是private类型,实现了代码属性的封装。在这里还使用了正则表达式和List接口中的ArrayList,还有迭代器Listterator(只能实现从前向后的输出),将匹配出来的字符串删除注释部分(//后面和/* */ 以及“ ”中间的部分)后放进List里面,然后再将List中的".""("")"","";""[""]""-""*""/""+"">""=""!"":""\\""||""[^a-zA-Z]"删除(用空格replace)。再对List中的字符串挨个与53个关键词进行匹配,如果相同则记录出现次数的数组加1。最后将关键词以及出现关键词的个数输出即可。
(3)踩坑心得
在对输入字符串处理时,我最开始是打算使用group方法,将注释前的部分和引号前后的部分放入List中,然后将剩下的字符串再挨个把单词提取出来再放到另外一个数组中。但是考虑到这样将单词挨个提取出来很麻烦,因为不知道一个字符串里有多少个单词,并且没办法判断是否字符串读取结束。于是改变了思路,还是将注释前的部分和引号前后的部分放入List中,接着将字符串中的运算符号以及括号等等用空格replace掉,之后再将剩下的单词挨个与53个关键词匹配。
(4)改进建议
通过这几次作业对正则表达式中的匹配问题已经有了一些了解,但是对List和group等方法还是不够熟练,其中很多的方法都不是很熟悉,在之后的学习中,要重点关注一下这两个方面,毕竟正则表达式是一个非常重要的技术,还有List也是一个很常用的东西,要掌握牢!
3、第六次作业
(1)作业总体总结:这一次的题目集整体难度不大,题量适中,主要是难度不大所以完成的要比前几次作业快一点点。题目集7-1,7-3,7-4都是对正则表达式的训练,前面两道题都是非常基础的数字和字母匹配,只是7-4对学号的匹配处理有一些问题(只取1-40号),不过但查询资料后就很快的解决了((40|[1-3][0-9]))。7-2是对字符的排序,刚开始还挺疑惑的怎么将字符转化为ASCII码值,但是查阅资料之后知道字符可以直接比较(直接比较的就是ASCII码值大小),在理解这个原理之后就只需要对大小进行排序就可以解决。7-5是图形继承与多态和7-6 实现图形接口及多态性,两题都是对图形的练习,也是我下面重点分析的两题。
(2)题目分析
1)7-5分析:
圈复杂度以及类图



在7-5中,很难得的是圈复杂度终于是0了。在编写代码的过程中,尽量避免了if-else,switch,和循环的分支,所以将圈复杂度给降低下来了。该题将类中的属性都使用的是private型,这样就保证了各个类属性的封装性。设计了一个抽象的Shape类,Circle,Rectangle,Triangle类均是继承自Shape类,其中Shape类中还存在getArea(),validate(),toString()三个抽象方法,三个子类均从父类中继承各个方法,并且在各自的类中对三个方法进行复写,实现代码的多态。
在该题中还使用了Collections类,先是将所有面积的数据存放在List中,之后就可以便于List中的数据大小直接进行排序。
1 Collections.sort(list);
2)7-6分析:
圈复杂度以及类图



7-6中各类中的属性仍然是private型保证了代码的封装性,设计一个GetArea的接口作为父类,Circle和Rctangle类继承自GetArea.这还是第一次接触接口,抽象类GetArea作为接口,它只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的功能,接口是百分之百的抽象类。在接口中需要使用interface这个关键字,使用后就不必去表明abstract,在子类中也要使用implements。
例如:
1 interface GetArea { 2 public double getArea() ; 3 }
4 class Circle implements GetArea{
5
6 }
该题还使用了多态,定义了指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能,实现了代码的多态性。但是在这里还需要加上类型的强制转换,这样才可以使用子类中的方法。
1 GetArea c = new Circle(); 2 GetArea r = new Rectangle(); 3 4 ((Circle) c).setRadius(radius); 5 ((Rectangle) r).setLength(length); 6 ((Rectangle) r).setWidth(width);
3)7-1,7-3,7-4分析:
7-1是匹配QQ号,其中主要考察的是对数字的匹配,相较于其他两题算是最简单的一道题,只需要直接对数字挨个进行匹配,但是要注意QQ号的位数,因为QQ号的位数是5-15位不等,所以需要用 ? 去使有的位数可以存在也可以不存在。
7-3是匹配验证码,在这就存在一个出现的字符可以是数字也可以是字母,所以使用了 [0-9a-zA-Z] 这样的匹配方式,代码的意思就是出现0-9数字或者a-z,A-Z的字母即可匹配,这样就可以解决这个问题。其次是验证码刚好是四位数的验证码,所以就存在一个出现次数的问题,[0-9a-zA-Z]{4} 这样就代表可以出现四次。
7-4是学号校验,一共是八位数,均是数字,首先是班级的问题,只存在固定的几个班,([1][1-7]|[6][1]|[7][1-3]|[8][1-2]),将班级的部分用括号括起来中间,将三个不同的方向班级用 | 分开,再用括号将学号的两位数括起来,将学号分为个位数匹配 0[1-9] 和10-39的两位数匹配 [1-3][0-9] 和 40 三个类型用 | 去隔开就可以匹配01-40的学号。
(3)踩坑心得
在题目要求里说明了7-6题需要使用到多态,于是我想到了用父类对new一个子类的新对象,但是在这是出现了一个问题,新的对象没有办法使用子类的方法,只能使用父类的方法,于是使用了老师上课说的强制转换方法改进,将对象强制转换为子类,这样就可以使用子类中的方法。
在处理接口问题的时候,一直单纯以为接口和抽象类差不多,但是后来发现二者还是差好多。首先在抽象类里面是使用abstract而在接口里面是interface。接口中可以定义成员变量,但是这些成员变量默认都是public static final的常量。接口中没有已经实现的方法,全部是抽象方法,但是抽象类中可以没有抽象方法。一个类实现某一接口,必须实现接口中定义的所有方法。
(4)改进建议
在这次作业中第一次接触了接口,大致的理解了接口和抽象类的差别,但是还是不是很熟悉。还有多态方面,觉得父类子类继承真的很奇妙,不同的写法有不同的作用,还有竟然可以将对象直接强制转换。这两个点在之后的学习中也要不断强化,加深理解,多在网络上看看大神们的分析和示例。最后是正则表达式,虽然现在在匹配方面问题还不大,但是后续还有group分组和其他很好用的方法,都要加紧快点学会,毕竟正则表达式太重要了!!
二、总结
从这三次的作业中还是收获了很多东西的,有的题目确实有点挑战但是真的很锻炼人的能力,也在题目集里面发现自己还是有很多不太懂的知识点。这次较上一次作业来说,我感觉还是有很多进步的,比如在这次的作业中,圈复杂度真的降低的挺多,而且对日期还有图形面积的操作越来越熟练了,正则表达式也有一定进步,真是想不到当初我以为非常非常难的知识点竟然慢慢也可以上手运用了(虽然运用的还不是很熟练)。但是还是有挺多问题的。首先是一些新的知识点,比如接口,这是第一次接触到,感觉这个知识点才刚刚开头,还有好多要学习的方面,虽然这次作业解决了接口问题,但是感觉还不是很熟练,所以之后要多留意这方面。还有List、Set或MapJava集合框架应用,List在三个方法中算是我们接触稍微多一点的,但是还是不是很熟悉,尤其是迭代器是一个很实用的东西,所以也要将这个知识点好好认真对待。

浙公网安备 33010602011771号