一、前言
1.第四次作业(答题判题程序4)
这次作业题目在原先的题型类型上新增了多选题和填空题,考虑到和原来的题目具有相同的属性,我果断选择使用当时刚学的继承来描述这两种新题型信息,但是新题型的分数计算比较复杂,只好多用几个if语句来加强判断了。新增的多名同学多张卷,以及同一个同学对不同试卷需要排序,我选择先按学号排序,再重新遍历并对于学号相同的试卷之间进行试卷号的排序,虽然时间的复杂度有点高,但也不失为可行的笨办法,否则用hashmap可以有更好的方法。这次作业的难度适中,但不好拿高分,主要在多张试卷的排序上,数量少点还好说,多起来我的排序便不管用了,其次便是没有考虑到未作答以及白卷的情况。
2.第五次作业(家居强电电路模拟程序-1)
这次作业着重考察继承和多态的使用,电器间的关系复杂又自成一脉,我将其总体分为电路、控制器、受控制器。在理清对象关系上时间花了不少,本来根据电器的属性描述书写了不少成员变量和方法,后面直接看到具体输入信息发现多余了,索性直接根据题目输入信息设置变量。这三个类父类拥有一个共同的父类ElecLoad,它具有名字、输入输出电压及相应的编号等基础属性。不同类之间具有相同或相似的属性较多,因此关系相对明确,能够相对较完善的得到一个初步的认识。这次的作业比较容易,总体分为三个步骤,信息的输入读取,电压的计算,电器的信息输出,所有步骤在主方法便可完成,不是很复杂。甚至对正则表达式的需求也不是很大。唯一的难点便是对于输出时要按照特定的顺序,直至这次作业的截至都没相出一个较好的方法。
3.第六次作业(家居强电电路模拟程序-2)
这次作业虽然只在上一次的基础上干路上迭代了一个并联电路,但不管是代码还是步骤数都是激增,更为要命的是测试点的提示不在开放,而样例中只有看看三个,且所设计的范围也是比较小的。因此这意味者我们需要自己设计各种可能且具有代表性的样例,这又在无形中增添了难度。同时为了解决上次作业遗留的排序问题,我特意创建了一个Show类用来备份读入的对象信息,一方面不影响原先各种操作,另一方面增加对不同对象的针对性操作,如同类型对象排序,输出等。本次主要涉及知识点变化不大,主要增加的类之间的关系,题目难度激增,过程更是又原先的3步变成了输入->控制器操作->判断并联电路断联情况->计算电阻->计算电压->排序->输出。如果采用传统列表遍历的方式将面临多层嵌套的问题。
二、设计与分析
1.先看一下代码的复杂度
method | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
Anspaper.addSqa(String) | 2.0 | 1.0 | 3.0 | 3.0 |
Delete.addDelete(String, Paper) | 7.0 | 4.0 | 5.0 | 5.0 |
Main.anspapername(ArrayList |
6.0 | 1.0 | 4.0 | 4.0 |
Main.endscore(Anspaper) | 1.0 | 1.0 | 2.0 | 2.0 |
Main.ismanfen(ArrayList |
5.0 | 1.0 | 4.0 | 4.0 |
Main.main(String[]) | 9.0 | 1.0 | 9.0 | 9.0 |
Main.pinfen(ArrayList |
19.0 | 8.0 | 8.0 | 9.0 |
Main.sortanspaper(ArrayList |
16.0 | 1.0 | 8.0 | 8.0 |
Main.sortpaperfen(ArrayList |
6.0 | 1.0 | 4.0 | 4.0 |
Paper.addQA(String) | 1.0 | 1.0 | 2.0 | 2.0 |
Paper.searchqa(int, int, Anspaper, int) | 27.0 | 6.0 | 8.0 | 8.0 |
Paperfen.addFenzhi(String) | 2.0 | 1.0 | 3.0 | 3.0 |
PaperK.addQA(String) | 1.0 | 1.0 | 2.0 | 2.0 |
PaperK.searchqa(int, int, Anspaper, int) | 38.0 | 9.0 | 9.0 | 9.0 |
PaperZ.addQA(String) | 1.0 | 1.0 | 2.0 | 2.0 |
PaperZ.searchqa(int, int, Anspaper, int) | 65.0 | 9.0 | 13.0 | 13.0 |
Student.addStu(String) | 1.0 | 1.0 | 2.0 | 2.0 |
可以看到其中PaperZ.searchqa(int, int, Anspaper, int)方法的复杂度达到了惊人的65,这是因为套用了4重循环,这也侧面反映了传统的使用ArrayList来进行查找操作时的诸多不便,并且调试的过程也变得异常艰难
class | OCavg | OCmax | WMC |
---|---|---|---|
Anspaper | 3.0 | 3.0 | 3.0 |
Delete | 5.0 | 5.0 | 5.0 |
Fenzhi | 0.0 | ||
Main | 5.7 | 9.0 | 40.0 |
Paper | 5.0 | 8.0 | 10.0 |
Paperfen | 3.0 | 3.0 | 3.0 |
PaperK | 5.5 | 9.0 | 11.0 |
PaperZ | 7.5 | 13.0 | 15.0 |
QA | 0.0 | ||
Sqa | 0.0 | ||
Stu | 0.0 | ||
Student | 2.0 | 2.0 | 2.0 |
这是类关系图
PaperK和PapaerZ与Paper是继承关系,因为他们的属性相同,只有评分标准不同,因此只需重写评分方法和信息的输入就行
2.先看复杂度
method | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
Alspeed.Alspeed() | 0.0 | 1.0 | 1.0 | 1.0 |
Alspeed.Alspeed(double, int) | 2.0 | 1.0 | 1.0 | 3.0 |
Alspeed.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Alspeed.setDang(String) | 2.0 | 1.0 | 1.0 | 3.0 |
Bai.Bai() | 0.0 | 1.0 | 1.0 | 1.0 |
Bai.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Bai.getBright() | 3.0 | 1.0 | 1.0 | 3.0 |
BeControler.BeControler() | 0.0 | 1.0 | 1.0 | 1.0 |
Bus.addElec(ElecLoad) | 0.0 | 1.0 | 1.0 | 1.0 |
Bus.Bus() | 0.0 | 1.0 | 1.0 | 1.0 |
Controler.getOut() | 0.0 | 1.0 | 1.0 | 1.0 |
ElecLoad.display() | 0.0 | 1.0 | 1.0 | 1.0 |
ElecLoad.setDang(String) | 0.0 | 1.0 | 1.0 | 1.0 |
Fan.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Fan.Fan() | 0.0 | 1.0 | 1.0 | 1.0 |
Fan.getRunspeed() | 4.0 | 1.0 | 1.0 | 4.0 |
Fenspeed.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Fenspeed.Fenspeed() | 0.0 | 1.0 | 1.0 | 1.0 |
Fenspeed.Fenspeed(double, int) | 0.0 | 1.0 | 1.0 | 1.0 |
Fenspeed.setDang(String) | 6.0 | 1.0 | 2.0 | 5.0 |
Lamp.Lamp() | 0.0 | 1.0 | 1.0 | 1.0 |
Main.main(String[]) | 70.0 | 1.0 | 24.0 | 25.0 |
Of.display() | 2.0 | 1.0 | 2.0 | 2.0 |
Of.getOut() | 1.0 | 2.0 | 1.0 | 2.0 |
Of.Of() | 0.0 | 1.0 | 1.0 | 1.0 |
Of.setDang(String) | 2.0 | 1.0 | 1.0 | 2.0 |
Ri.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Ri.getBright() | 2.0 | 1.0 | 1.0 | 2.0 |
Ri.Ri() | 0.0 | 1.0 | 1.0 | 1.0 |
Total | 94.0 | 30.0 | 54.0 | 70.0 |
Average | 3.2 | 1.0 | 1.8 | 2.4 |
class | OCavg | OCmax | WMC |
---|---|---|---|
Main | 25.0 | 25.0 | 25.0 |
Fenspeed | 2.0 | 5.0 | 8.0 |
Of | 1.75 | 2.0 | 7.0 |
Fan | 1.7 | 3.0 | 5.0 |
Alspeed | 1.5 | 2.0 | 6.0 |
Bai | 1.3 | 2.0 | 4.0 |
Ri | 1.3 | 2.0 | 4.0 |
BeControler | 1.0 | 1.0 | 1.0 |
Bus | 1.0 | 1.0 | 2.0 |
Controler | 1.0 | 1.0 | 1.0 |
ElecLoad | 1.0 | 1.0 | 2.0 |
Lamp | 1.0 | 1.0 | 1.0 |
Pin | 0.0 | ||
Total | 66.0 | ||
Average | 2.2 | 3.8 | 5.0 |
可以看到其他类的复杂度较低,主要都是集中在主方法中,其中的输入一块稍显臃肿
类图关系如下
可以看到所有类之间关系密切,三个开关,三个用电器
3.代码复杂度
method | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
Alspeed.Alspeed() | 0.0 | 1.0 | 1.0 | 1.0 |
Alspeed.Alspeed(double, int) | 2.0 | 1.0 | 1.0 | 3.0 |
Alspeed.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Alspeed.setDang(String) | 2.0 | 1.0 | 1.0 | 3.0 |
Alspeed.setV() | 0.0 | 1.0 | 1.0 | 1.0 |
Bai.Bai() | 0.0 | 1.0 | 1.0 | 1.0 |
Bai.Bai(double, String) | 0.0 | 1.0 | 1.0 | 1.0 |
Bai.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Bai.getBright() | 6.0 | 2.0 | 1.0 | 4.0 |
Bbus.caculate() | 5.0 | 1.0 | 4.0 | 5.0 |
Bbus.setV(double, double, double) | 7.0 | 1.0 | 4.0 | 5.0 |
BeControler.BeControler() | 0.0 | 1.0 | 1.0 | 1.0 |
BeControler.BeControler(double, String) | 0.0 | 1.0 | 1.0 | 1.0 |
Bus.addElec(ElecLoad) | 0.0 | 1.0 | 1.0 | 1.0 |
Bus.Bus() | 0.0 | 1.0 | 1.0 | 1.0 |
Controler.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Controler.getOut() | 0.0 | 1.0 | 1.0 | 1.0 |
Controler.setV() | 0.0 | 1.0 | 1.0 | 1.0 |
D.D() | 0.0 | 1.0 | 1.0 | 1.0 |
D.D(double, String) | 0.0 | 1.0 | 1.0 | 1.0 |
D.display() | 0.0 | 1.0 | 1.0 | 1.0 |
D.getRunspeed() | 7.0 | 2.0 | 1.0 | 6.0 |
ElecLoad.caculate() | 0.0 | 1.0 | 1.0 | 1.0 |
ElecLoad.display() | 0.0 | 1.0 | 1.0 | 1.0 |
ElecLoad.setDang(String) | 0.0 | 1.0 | 1.0 | 1.0 |
ElecLoad.setV() | 0.0 | 1.0 | 1.0 | 1.0 |
Fan.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Fan.Fan() | 0.0 | 1.0 | 1.0 | 1.0 |
Fan.Fan(double, String) | 0.0 | 1.0 | 1.0 | 1.0 |
Fan.getRunspeed() | 0.0 | 1.0 | 1.0 | 1.0 |
Fbus.caculate() | 6.0 | 4.0 | 3.0 | 4.0 |
Fbus.setV(double) | 10.0 | 1.0 | 5.0 | 5.0 |
Fenspeed.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Fenspeed.Fenspeed() | 0.0 | 1.0 | 1.0 | 1.0 |
Fenspeed.Fenspeed(double, int) | 0.0 | 1.0 | 1.0 | 1.0 |
Fenspeed.setDang(String) | 6.0 | 1.0 | 2.0 | 5.0 |
Fenspeed.setV() | 0.0 | 1.0 | 1.0 | 1.0 |
Lamp.Lamp() | 0.0 | 1.0 | 1.0 | 1.0 |
Lamp.Lamp(double, String) | 0.0 | 1.0 | 1.0 | 1.0 |
Luo.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Luo.getRunspeed() | 11.0 | 2.0 | 1.0 | 9.0 |
Luo.Luo() | 0.0 | 1.0 | 1.0 | 1.0 |
Luo.Luo(double, String) | 0.0 | 1.0 | 1.0 | 1.0 |
Main.main(String[]) | 137.0 | 15.0 | 52.0 | 53.0 |
Of.display() | 2.0 | 1.0 | 2.0 | 2.0 |
Of.Of() | 0.0 | 1.0 | 1.0 | 1.0 |
Of.setDang(String) | 2.0 | 1.0 | 1.0 | 2.0 |
Of.setV() | 0.0 | 1.0 | 1.0 | 1.0 |
Ri.display() | 0.0 | 1.0 | 1.0 | 1.0 |
Ri.getBright() | 5.0 | 2.0 | 1.0 | 3.0 |
Ri.Ri() | 0.0 | 1.0 | 1.0 | 1.0 |
Ri.Ri(double, String) | 0.0 | 1.0 | 1.0 | 1.0 |
Show.display() | 21.0 | 1.0 | 15.0 | 15.0 |
Show.Show() | 0.0 | 1.0 | 1.0 | 1.0 |
Show.sort(ArrayList |
10.0 | 1.0 | 5.0 | 5.0 |
Total | 239.0 | 76.0 | 138.0 | 168.0 |
Average | 4.3 | 1.4 | 2.5 | 3.1 |
复杂度依然主方法高,显然计算代码集中在此,因为我将计算电阻和判断断联情况放在一起,导致有点层次不分,故而增加的复杂度。
class | OCavg | OCmax | WMC |
---|---|---|---|
Main | 51.0 | 51.0 | 51.0 |
Show | 7.0 | 15.0 | 21.0 |
Bbus | 4.5 | 5.0 | 9.0 |
Fbus | 4.5 | 5.0 | 9.0 |
Luo | 2.25 | 6.0 | 9.0 |
D | 2.0 | 5.0 | 8.0 |
Fenspeed | 1.8 | 5.0 | 9.0 |
Bai | 1.5 | 3.0 | 6.0 |
Of | 1.5 | 2.0 | 6.0 |
Ri | 1.5 | 3.0 | 6.0 |
Alspeed | 1.4 | 2.0 | 7.0 |
BeControler | 1.0 | 1.0 | 2.0 |
Bus | 1.0 | 1.0 | 2.0 |
Controler | 1.0 | 1.0 | 3.0 |
ElecLoad | 1.0 | 1.0 | 4.0 |
Fan | 1.0 | 1.0 | 4.0 |
Lamp | 1.0 | 1.0 | 2.0 |
Pin | 0.0 | ||
Total | 158.0 | ||
Average | 2.9 | 6.4 | 8.8 |
三、踩坑心得
1.为了将题目要求的信息读取并存储,我创的类有点过多了,有好几个是可以整合到一起的,这样既可以减少不必要的遍历,也可以便于调试时数据的查看,比如几个问题与答案完全可以统一。其次这次作业出现多次的根据某个变量在查找另一变量并操作的情况,使用ArrayList存储信息每次都要遍历才能找到,时间复杂度高,所需要的循环嵌套多,并不适用于本次题目的场景。因此在理清对象的关系后,选择一个合适的list将有助于后续代码的书写和思考。
可以看到多重循环和if语句使得可读性有所降低,修改起来也颇为麻烦
2.输入使用正则和String类的一些方法进行信息的甄别,但对于类似[VCC L1-1]一块的处理并不妥善,我想的是通过区分左右信息是不是“VCC”和“GND”来选择新添的对象,并同时确定电路的输入端和输出端以及给予相应的电压,如语句bus.mainbus.get(bus.mainbus.size()-1).in.v=220;
然而未考虑到List中是否有元素,好在本次作业测试点并未有这方面的考量,但这为下次作业我整的我崩溃的清一色的“非零返回”埋下伏笔。不过好在这次的槽点不算多,一方面毕竟是这种题型的作业的第一次,还未进行迭代,故而需考虑的地方较少,其次题目所需要的计算较少,步骤亦是如此,只需简单的遍历操作和输出即可。
3.这次作业没有将各个步骤拆分为多个方法进行,在进行计算电阻和判断断联情况为将其拆分,导致有点绕和层次不分,Show类的创建极大的简化了我的排序过程,
并且可以更有针对性的解决的列表遍历时的多重嵌套问题,毕竟修改前我需要重循环的操作一下便做到了。
对于以往需要多重循环考虑在干路还是在并联的支路上,如今只需到相应的类型的列表中寻找
四、改进建议
1.(1)可以使用hashmap重新建立信息间的联系,这样在根据已知信息进行查找时会方便;
(2)重新审视类的关系,使用继承来简化属性和方法;
(3)减少多重循环的使用,增加更多注释来方便解读步骤;
2.(1)更改输入时[]内信息的读取,原先的代码并未考虑到列表集合为空的特殊情况;
(2)改进电器的输出排序相关的方法,可以通过创建对应的类的列表专门存储同一类对象的信息,从而更好的进行排序并输出;
3.(1)分步进行操作,创建多个方法各司其职,增强可读性,同时也不会显得主方法头重脚轻;
(2)输入部分过于臃肿,全是if的条件语句用于区分情况,不利于调试和阅读;
(3)干路和并联的支路具有相同的属性,应属于同一类型,应将他们统一到一个类中;
五、总结
相较于上次对于正则表达式的考察,这三次注重于对类的关系和继承多态的理解和使用。通过这三次作业的多次实践我进一步理解和掌握了继承和多态的概念和用法,同时对类间关系有了进一步的理解,也更加深入的明白的hashmap与ArrayList的优劣和各自的适用场景。
建议:建议PTA作业最后两天开放测试点的提示;