第5、6、7次题目集总结

一、前言

第五次题目集题目量较大,第1、2题基于之前C语言题型之上考察对Java基础语法的掌握能力;第3、4题则考察新学习的正则表达式知识点;前四题难度相对较低,第5题正式开始提升难度,考察面向对象程序设计思维,开始对对象与类有了初步的认识,同时基于面向对象设计原则开始处理复杂的现实问题,正式开始迭代型电梯调度问题。
第六次题目集题目量减小,第1、2题同样继续考察面向对象程序设计思维,不过这两题复杂度相对较低,做好类与对象的设计,算法方面不难;第3题开始进行迭代,难度提升,此次有类图作为引导,规范我们对类与对象的设计,同样考察对面向对象程序设计思维能力,算法难度较大,要考虑到多种不同的请求方案。
第七次题目集题目量不变,同样是三题,第1题依旧考察面向对象设计思维,此题难度较低;第2题难度提升,重点考察对一些比较复杂问题的面向对象设计思维,要充分理解各类之间的调用关系,同时算法稍稍变难了一些;第3题则继续进行电梯调度问题迭代,算法逻辑进行了改变,难度达到一个新的水平,但算法逻辑进行了简化。

二、设计与分析

1.第五次题目集电梯程序

题目类设计要求:
请编写一个Java程序,设计一个电梯类,包含状态管理、请求队列管理以及调度算法,并使用一些测试用例,模拟不同的请求顺序,观察电梯的行为是否符合预期,比如是否优先处理同方向的请求,是否在移动过程中处理顺路的请求等。

设计类图:

Main类:主要处理请求队列合法输入,进行运行。
Elevator类:exchangeFloor方法用于将队列请求转化为楼层信息;validInput方法用于判断楼层信息是否符合最小最大楼层之间;movingprint、stoppedprint方法都用于控制输出格式;generalScheduling方法用于将队列分为内外部请求;findNextFloor方法用于找到下一楼层;run方法则控制电梯运行。

SourceMonitor代码分析:

Average complexity(平均复杂度):9.00
Average Block Depth(平均块深度):4.01层
Average Statements per Method(每个方法平均语句数量):20.00
Comments(注释占比):15.7%
Classes(类数量):2
根据数据分析,第一次写的电梯程序代码过于复杂,深度较大,每个方法语句过多,注释量少。主要是第一次写电梯程序,算法较难,加上个人应对这种复杂问题能力较薄弱,导致将太多的语句以及分支杂糅在一个方法中,算法逻辑较为复杂,难以理解,最主要还是个人能力薄弱,对复杂问题处理经验较少,导致代码写的较差。
(其中复杂度最大的方法在于findNextFloor中,用了太多if,else语句进行判断各种队列情况,导致分支过多,复杂度增大)

2.第六次题目集电梯程序

题目类设计要求:
对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类。

设计类图:

Elevator类:主要是一些currentFloor,minFloor,maxFloor,direction属性的getter、setter方法,以及对队列楼层是否合法的判断。
Direction类:枚举类,列举了电梯的三种方向。
ExternalRequest类:用于处理外部请求,有floor,direction两种属性,getter方法能够反映外部请求的需求。
RequestQueue类:主要是内外部队列的getter,setter,add方法,用于处理队列请求,将内外部请求分开存储。
Controller类:除getter,setter方法外,进行了电梯程序主要的算法处理,最关键的是getNextFloor方法,主要是处理各种方案的算法(进行了多次if,else判断),返回下一层楼的值;openDoors、move都是格式化输出方法,其中因为需要额外输出第一层的内容,需要firstmove、firstRequest方法来特殊处理第一层(逻辑重复了,其实可以简化,下一次程序进行了简化);remove方法则是删掉已经完成的请求。
Main类:同上次,主要进行输入处理,将输入内容存入到LinkedList中。

SourceMonitor代码分析:

Average complexity(平均复杂度):3.79
Average Block Depth(平均块深度):3.45层
Average Statements per Method(每个方法平均语句数量):7.76
Comments(注释占比):16.6%
Classes(类数量):6
根据数据分析,此次代码平均复杂度较上次低了不少,深度也有所降低,方法语句也减少了,因为代码量变大了注释也相应增多了一些,类数量按要求增多了许多。总体而言,经过类与对象的设计,使得代码不会过于集中于一个方法,加上有了第一次的经验每个方法的语句数都做了一些精简化处理,去除了部分多余重复的代码逻辑,因而复杂度减小了,相比于上次进步了不少。但同时由于编程能力较弱,findNextFloor方法还是过多if,else分支,导致最大复杂度仍然较大。

3.第七次题目集电梯程序

题目类设计要求:
对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类。

设计类图:

Elevator类:同第六题设计,一些getter、setter方法以及合法输入判断。
Direction类:同第六题设计。
ExternalRequest类:同第六题设计。
RequestQueue类:同第六题设计。
Passenger类:有sourceFloor,destinationFloor属性用于存储内外部请求的楼层需求,此类与第六题不同的是一个类同时将内外部请求归纳到一起,仅保留了楼层信息(因为算法逻辑进行了变化),同样的是主要是getter、setter方法获取内外部请求信息。
Controller类:大致上与第六题相似,但做了简化,取消了firstRequest方法,因为经过检查后发现与getNextFloor算法大致一样,没必要重复设计方法,所以删掉了这部分方法。
Main类:与第六题相似,只对题目改变的外部请求格式输入进了一些变化。

SourceMonitor代码分析:

Average complexity(平均复杂度):3.19
Average Block Depth(平均块深度):3.54层
Average Statements per Method(每个方法平均语句数量):6.50
Comments(注释占比):13.7%
Classes(类数量):6
根据数据分析,相比较前两次代码复杂度下降明显(从9.00-3.19)说明代码更加简洁,重复算法逻辑较少,平均深度也控制在3.5层左右(较为良好),每个方法平均语句数量也大幅减少(从20.00-6.50),对此问题的理解程度更深刻,因而比较掌握了其中的本质,语句量得以减少。注释量减少主要还是因为理解了概念,就没有过多的解释了(缺陷)。

三、踩坑心得

  1. 输入方面的小细节,在每次进行input.nextInt/input.nextDouble等等之后,注意会残留一个换行符,如果你不对它进行如下处理的话,你下一次使用input.nextLine输入的时候,此时输入的数据将无法合适地存储到想要的位置,因为它会把这个换行符给读取进去,导致这个数据为空的而不是你要输入的数据。
  2. 在输出时要注意要对第一次输出进行特殊处理,如下图,先进行输出第一层楼梯的情况,因为在每次判断完下一层电梯再次运行的时候都是currentFloor++的,不会重复输出当前楼层情况,否则就得不到想要的输出结果,其余输出就先对currentFloor先++再输出。

    否则就会这样

    3.在每次进行判断下一个执行的楼层的时候千万千万要分类考虑(判断是否有哪个队列是空的),因为你不知道有没有队列其实已经空了(即处理完了),如果不这样考虑的话,在某一次对比队头的时候就会出现outOfIndex的错误情况。

    4.同时要注意对两队列都是空的情况进行特殊化处理,如果都为空那么就要返回一个用于标志的值(我这里是将返回的nextFloor值是否为0来作为标志),说明此时已经处理完请求了要退出循环,否则就容易运行超时,当然这也是判断循环是否继续进行的条件。(很关键,因为我很多次都是因为这个超时了退不出循环)

    5.图片如下,注意到一点,判断currentFloor是否大于返回的nextFloor来判断电梯的运行方向,为什么呢?因为就算下一个请求是执行外部请求,它的方向是Down但是也可能它在电梯当前楼层的上面,所以电梯要上去接他,所以运行方向以当前楼层和目标楼层的大小关系为准。

    6.一个小tips,与c语言有所不同的是,java语言是有>=和<=这种合并在一起的逻辑运算符的,不需要再像c语言一样做下面这样的判断了。

    7.如果存在多个相同的请求,那么在删除完相同的请求后注意也要返回当前楼层,只不过可以不对重复的请求进行输出就可以了,避免nextFLoor被误判为0而提前结束了循环。(多次坑总结而来)

    8.还有一个非常重要的点,就是如果经过算法处理后发现是先执行外部请求,那么就要保存好此时外部请求的方向,因为如果电梯是向上去接这个外部请求,而它的请求方向是DOWN,但此时电梯的运行方向是UP,如果到了外部请求这层不去把UP这个状态该为DOWN的话,下次处理请求就会优先向上走,而不是向下走导致错误,例如下面的情况。


    而正确的处理是应该执行完<5,DOWN>这个请求后向下去接<1>而不是继续UP到<6,UP>这里,所以要保存好外部请求的方向,在执行完之后及时更换电梯方向。
    9.提供一些小小的建议,就是多测一些比较不一样的样例,你会得到不一样的效果,很可能你就会发现你有很多方面是没有考虑周全的(hhh)。

四、改进建议

1.多写一些注释,不只是为了方便自己下次定位,更是让别人来理解自己的代码,在别人有新的进展之后,可以有效帮助你找到代码问题,有效提升沟通效率。
2.方法多做一些,尽量不要让太多代码集中在要求一个地方,否则复杂度太高了,不利于维护。
3.写代码之前理清楚逻辑,明确各类之间的调用关系,以及各方法分别是什么作用,就可以避免出现第一次代码一样结构过于混乱,单个方法代码过多,以致于难以维护,也不便于后续阅读。
4.其实属性名称尽量不要太长(不然容易超过代码长度限制hh),然后在每次使用该属性的时候直接选中提示框里你需要的属性(大部分新版本编译器都有这样的功能),非常有助于你快速准确的写好代码,也不会出现一些非常低级的错误。
5.多学习一些java基础语法,java中有很多语法与c语言不一样,很多都是简化过的,可以帮助你简化很多代码,例如floor>minFloor||floor==minFloor直接可以简化为floor>=minFloor,并且有很多很实用的工具,像LinkedList这样的很多方法可以直接用不需要再去写了,简化了很多。
6.尽量把重复的,相似的算法部分压缩成一个方法,设置好参数直接调用,不要老是ctrl+c、ctrl+v,直接调用就好了,非常有利于降低复杂度和维护。

五、总结

一、学习到的内容:
1.提高了一些java基础语法的掌握能力。像如何写类和方法;应该用public还是private;类型应该是int,double还是String;如何写类的构造方法,getter,setter怎么写;原来定义的类还能当作一种类型被使用;在使用<>来定义LinkedList或ArrayList类型的时候是用int还是integer等等。
2.学习到了枚举类型是什么,该怎么使用,有什么好处。
3.学习到了如何设计类与对象,每个类应该包含哪些方法,每个类之间该如何调用,是否应该创建一个对象进行调用等等。
4.学习到了正则表达式是什么,怎么去正确的使用它,该在什么场景下应用,如何快速的提取到想要的信息。

二、仍需学习和提升的地方:
1.算法能力还需要提高,目前对于解决复杂问题的思路太少,写了太多复杂、重复和难以理解的算法代码,以致于后续改进比较困难,不知道改哪,导致程序频繁出错。
2.设计类与方法的能力也需要提高,现在设计的类与方法大多数都是在参照老师给的内容,没有设计好适合自己的方法,有时候很多代码都可以放进一个方法里面,但是没有考虑周全导致老是写重复的代码。
3.以后多多学习如何做一些项目,提高自己应对复杂问题的能力,并且形成大局观,能形成比较流畅的思路,提高思维能力。
4.多学习java的一些好用的工具,提高编程效率。

三、建议与意见:
1.希望老师能多提供一些好的学习资源和好的学习工具,帮助大家更系统、更全面地学习java课程。
2.希望老师们能够多教大家一些能与当今行业相接轨的知识和热点,让我们能更好的融入到行业当中,所做的内容与行业所关心的息息相关。
3.希望老师可以偶尔演示一下该如何分析一下比较复杂的项目,该从哪起手,怎么设计类与方法,实操一下看看行业里的程序员是如何分析问题的。

posted @ 2025-04-18 17:52  北纬25度  阅读(72)  评论(0)    收藏  举报