单步电梯调度

news/2025/11/21 13:43:31/文章来源:https://www.cnblogs.com/ansyc/p/19252326

单步电梯调度程序

第一阶段大作业总结,第一次写markdown博客,老传统:Hello World! 😉
来自 NCHU 23级 物联网工程 ❤️

1. 前言

1.1 知识点覆盖

  • JAVA基础语法

    • 枚举类:定义电梯状态(Stopped/Moving)、方向(UP/DOWN/IDLE)
    • 正则表达式:用于匹配输入,Pattern类和Matcher类的使用,提取楼层、方向等核心参数。
  • 数据结构

    • 队列:基于 FIFO 特性,专门存储电梯内部请求与外部请求,有序管理请求处理顺序,契合电梯 “先呼叫先响应” 的基础逻辑。(虽然每次只比较队首)
  • 面向对象特性

    • 职责划分:按功能划分 Elevator(电梯实体)、RequestQueue(请求存储)、Controller(调度中枢)、Passenger(乘客请求封装)等类,实现高内聚、低耦合;

    👍"各人自扫门前雪,莫管他人瓦上霜"

    • 封装:核心属性设为私有,通过 getter/setter 方法控制访问与修改,保障数据安全性。

    封装=类+访问控制

  • 核心调度算法(LOOK算法)

    • 核心策略:同向优先,就近匹配。

    • 停靠原则:合理处理内部与外部请求的优先级,确保调度高效有序。

    其实很多时候bug🐛就是少个if

  • 输入输出

    • 输入处理:解析内部<楼层>、外部<楼层,方向>或<srcFloor,dstFloor>的格式请求,识别end关键字终止输入;
    • 输出处理:打印电梯当前楼层、运行方向及开关门信息,关键在于打印时机的控制。

1.2 题量

三次题目均基于LOOK算法实现,聚焦电梯调度核心场景,每次都只处理两个队列的队首元素。

由于老师贴心地提供了三次的类图,所以代码中的几个主要类,如:ElevatorRequestQueueController这三个类的大部分接口三次作业都是一致的。代码复用性较高。这样就可以集中精力攻克调度逻辑和输入输出调用时机适配的问题。

这也说明了好的类设计,真的能够提高代码的可维护性和可扩展性。
一想到后几次的大作业还要自己设计类图,哭了!😢😢😢

1.3 难度

按照正常情况三次作业的难度应该是依次递增,但由于老师提供了好类图,代码复用性较高,所以难度基本一致。我个人认为最难的是第一次,最简单是第二次,其次第三次。

但也可能是刚开始学习JAVA语言和面向对象的思想,所以第一次作业的难度最大。

2. 设计与分析

WEEK1

week1.1 类图设计

第一次作业没有提供对应的类图,所以我是根据自己对题目的理解写的题目,这个时候对面向对象还没有很深的理解(你说AI?我的评价是👎)。由于设计的PTA测试点只有一个,所以就没有思考太多,下面是类图(使用visio作图):
image-3

很明显,这个类图耦合度极高,所有的功能都在Elevator类中实现,根本没有可复用的部分,还是沿用了面向过程的思考方式,没有考虑到面向对象的封装性。

week1.2 核心思路

整体流程:
main读取输入
->
区分请求类型(含 "," 为外部请求,否则为内部请求)
->
调用 addInnerQueue/addOuterQueue 将请求加入对应队列(含楼层合法性校验)
->
调用 runElevator 启动电梯循环处理,直到队列清空:

  1. checkCurrentFloor:调用 setCurrentStatus(设置运行状态 Stopped/Moving)和 setCurrentDirection(设置运行方向 UP/DOWN/IDLE);
  2. 输出状态:若首次循环或非停靠状态,输出 "Current Floor: 楼层数 Direction: 方向";
  3. 移动逻辑:若状态为 Moving,按方向移动一层(UP 则 currentFloor++,DOWN 则 currentFloor--);
  4. 停靠处理:若状态为 Stopped,输出 "Open Door # Floor 楼层数"→"Close Door",调用 Poll 移除当前楼层的内部 / 外部请求;

若队列为空,设置方向为 IDLE、状态为 Stopped,程序结束。

week1.3 SourceMonitor分析报告

image-2

指标类别 具体数值/信息
代码行数 275
有效语句数 149
分支百分比 31.5%
函数调用语句数 33
注释比例 12.4%
类数量 4
方法数/类 3.00
方法平均语句数 9.75
最复杂方法 Elevator.setCurrentDirection()
最大复杂度 25
最深嵌套行数 137
最大嵌套深度 6
平均嵌套深度 3.40
平均复杂度 6.42

分析:

  1. 类少方法集中(类 = 4,方法 / 类 = 3.00):核心逻辑挤在Elevator,呈 “单体耦合”——Elevator包办调度、状态、存储,Main包办输入 + 启动,修改牵一发动全身。
  2. 方法 “臃肿”(setCurrentDirection()复杂度=25,嵌套深度 = 6):无模块化拆分,调试难。
  3. 可读性隐患(注释 = 12.4%):复杂逻辑缺步骤注释,嵌套太深(最深 137 行)。
  4. 复用性差(函数调用 = 33,分支 = 31.5%):条件判断密集(方向决策、停靠判断、合法性校验),但函数调用少,说明重复逻辑(如楼层合法性校验)未封装为独立方法,代码冗余。

第一次代码指标暴露 “单体耦合、逻辑集中” 的核心问题。

week1.4 踩坑心得

虽然第一次代码的质量不高,但也是踩了不少坑。😢

  • 没有设计,直接上手
    第一次作业的类图还是写这篇Blog才画的😆。没有事先画出类图,导致我写代码时想到哪,写到哪。比如,下面是开始的错误版本,我连枚举类都没想到使用:
if(IR.floor==this.currentFloor&&OR.floor==this.currentFloor){this.status="Stopped";}else if(IR.floor==this.currentFloor&&OR.floor!=this.currentFloor){this.status="Stopped";}else if(IR.floor!=this.currentFloor&&OR.floor==this.currentFloor&&OR.direction.equals(this.direction)){this.status="Stopped";}else{this.status="Moving";}

这个显然是没有考虑到全局,想到什么就写什么。👎

  • 没有面向对象的思想
    这一点从上面的分析报告也可以看出来。写代码时还是沿用面向过程的思想,所以在写代码时,没有考虑到类的封装性。
    最复杂的方法竟然是main方法,因为我没有设计好类图,写代码是时就把类简单看成一个可以调用函数的集合,例如我的Elevator类里出队的方法:
void Poll()

很难想象我的源码里有这样一种方法。在Elevator类里面有一个没有设置访问权限的成员方法,这显然不符合面向对象的封装思想。

week1.5 改进建议

  • 架构解耦,明确边界
    拆分三层模块:
    实体层(Elevator):仅管电梯状态(楼层、方向)和基础动作(移动、开关门);
    请求层(RequestManager):专门处理请求的添加、删除、校验和队列管理;
    调度层(Controller):协调前两层,实现方向决策、移动停靠逻辑。
  • 规范封装,访问控制
    方法名:Poll() → removeProcessedRequests()(明确是 “移除已处理请求”);

按照第二次作业给出的类图设计,就能实现较好的效果

WEEK2

week2.1 类图设计

此处偷一下懒,直接使用题目提供的类图😄

image-4

week2.2 核心思路

在看到类图并分析完后,及基本知道每个类的职责,通过每个的方法名,就基本猜出每个方法的作用,主要就是Controller类的方法:

  • void processRequests(): 处理输入请求的函数
  • void determineDirection(): 确定方向的函数,根据LOOK算法就大致知道这个的调用时机。
  • void move(): 移动的函数,电梯具体的运行肯定是这个方法,里面应该要调用方向判断,停靠判断和打印日志信息等方法。
  • boolean shouldStop(int floor): 停靠判断的方法
  • Integer getNextFloor(): 根据判断的方向移动一层的函数。
  • Integer getClosest(Integer a,Integer b): 获取最接近的楼层的方法。我认为这个方法可能用来根据当前方向和当前楼层,判断下一个应该停靠的楼层,类似与返回一个下一次停下目标楼层。(可能理解有误,但这个思路是可以实现的最终效果的👍)。
  • void openDoors(): 到达应该停靠的目标楼层,打印开门信息。
  • void removeRequests(int currentFloor): 需要停靠的目标楼层到达后,用于专门将其出队的方法,类似第一次我自定义的Poll()函数。

整体流程:
Controller主导调度,协调Elevator(电梯实体)和RequestQueue(请求队列)协同工作:

  1. 输入解析(Controller.processRequests()):
  • 读取最小/最大楼层,初始化Elevator实例;
  • 循环读取请求,通过正则解析内部请求(<楼层>)和外部请求(<楼层,方向>);
  • 校验楼层合法性,调用RequestQueue的addInternalRequest/>addExternalRequest加入队列(自动去重:避免连续相同请求);
  • 输入"end"(不区分大小写)终止输入。
  1. 调度启动(Controller.move()):
  • 先调用determineDirection()确定初始运行方向和目标楼层;
  • 进入循环(只要内外队列非空):
    a. 按方向移动到目标楼层:连续输出移动过程(如UP方向从当前楼层到目标楼层,逐行打印"Current Floor: X Direction: UP");
    b. 停靠判断(Controller.shouldStop()):检查当前楼层是否有需处理的请求(内部队首是当前楼层,或外部队首是当前楼层且方向与电梯一致);
    c. 若需停靠:输出"Open Door # Floor X"→"Close Door",调用removeRequests()移除当前楼层的已处理请求;
    d. 更新方向和目标楼层:再次调用determineDirection(),通过getClosest()找下一个最近的请求,设置新的方向和目标楼层;
    e. 重复步骤a-d,直至所有请求处理完毕。

week2.3 SourceMonitor分析报告

image-5

光看这次的图就知道,相较于上次,这次改进有多大😆👍

指标类型 具体数值
代码行数 383
有效语句数 234
分支百分比 21.4%
函数调用语句数 70
注释比例 9.9%
类数量 7
方法数/类 5.57
方法平均语句数 4.49
最复杂方法 Controller.processRequests()
最大复杂度 8
最深嵌套行数 159
最大嵌套深度 4
平均嵌套深度 1.73
平均复杂度 1.42

分析

  1. 分层架构初见成效,耦合度显著降低
    类数量=7,方法数/类=5.57 :相比第一次的单体耦合架构,本次拆分出Elevator(电梯状态管理)、RequestQueue(请求存储与去重)、Controller(调度中枢)、ExternalRequest(外部请求实体)及两个枚举类(Direction/State),实现了“职责初步分离”。
  2. 核心方法复杂度可控,模块化优势凸显
    没测试之前我以为最复杂的会是Controller.move()方法,但没想到竟然最复杂方法为Controller.processRequests(),最大复杂度=8,平均复杂度=1.42。也就是处理输入请求这个方法,进一步说明方法的整体复杂度显著降低。👍
  3. 注释与嵌套仍需优化
    注释比例=9.9%,最大嵌套深度=4,最深嵌套行=159 :虽最大嵌套深度从第一次的6降至4,但getClosest方法中仍存在4层嵌套(方向判断→距离对比→请求类型判断),逻辑层级较深,可能增加调试难度。

week2.4 踩坑心得

虽说是已有好的类图设计,但是仍然还是踩到一些坑。😢

  • 关于去重:
    观察测试用例知道这次相较于第一次需要进行去重操作。最初的去重操作我把他写在removeRequests(int currentFloor)这个方法中,也就是在移除请求的楼层时进行去重操作,具体如下面注释部分答代码:
if(IR!=null&&IR==currentFloor){queue.internalRequest.poll();/*//出队,同时移除当前连续的请求while(IR!=null&&IR==currentFloor){queue.internalRequest.poll();IR=queue.internalRequest.peek();}*/}ExternalRequest ER=queue.externalRequest.peek();if(ER!=null&&ER.getFloor()==currentFloor){queue.externalRequest.poll();/*//出队,同时移除当前连续的请求while(ER!=null&&ER.getFloor()==currentFloor){queue.externalRequest.poll();ER=queue.externalRequest.peek();}*/}

这个写本身是没有问题的,但是当我测试的时候,发现如果当前楼层既有内部又有外部请求时,这是后分两种情况:

  1. 外部请求的方向与当前电梯方向一致,也就是接下来还有同向的请求,这个外部请求应该出队。这个时候能够正常处理。
  2. 外部请求的方向与当前电梯方向不一致,也就是这个时候电梯要反向了,也就是只有当电梯反向后才能处理这个外部请求。也就是这个时候不能处理外部请求。但上面的代码会poll外部请求,出现bug。
    即使加上同方向的判断,这个时候也会出现一种情况,就是当前的请求是同方向的最后的请求。比如处理两个队首分别是<9><9,DOWN>,我的电梯此时方向为UP,到达了9层,之后也没有向上的层,这个时候也就是到达的层是UP方向的最后一层,也就是9。两个队首应该都要出队,这个时候就出现Bug了。

后来想了想,其实去重的操作完全可以在Controller.processRequests()中完成,只要记录前一次的请求,然后同新进队的请求比较是否相同,相同则不加入队列,不同则加入队列。
这么既能避免上述的情况,又能简化逻辑,将处理重复请求的潜在风险在一开始就消除。

  • 超时问题
    按照LOOK算法,每走一层,就要判断一下方向,这么做增加了时间开销,会反复调用determineDirection(),虽然最后的逻辑也是对的,但PTA会超时。
    这个时候我就想到停在当前目标楼层时,直到下一次停靠这中间是不需要判断方向的。也就是利用Elevator里的这个Status这个属性,做一次性处理。如果StatusSTOPPED,说明电梯已经停靠了,这个时候才判断方向;如果是MOVING,说明电梯正在移动,这个时候就不需要判断方向。
    本以为到这里就可以了,但是实现方法的不同也会造成时间开销的不同:
    最开始想到的是用for循环,增加一个私有属性TragetFloor,用来配合for实现(这里为了节省时间,我甚至都使用BufferedWriter bw),拿UP方向举例:
for(int i=elevator.getCurrentFloor();i<=elevator.getTargetFloor();i++){bw.write("Current Floor: "+i+" Direction: "+elevator.getDirection());bw.newLine();//elevator.setCurrentFloor(i);}

结果还是超时。但实际根本就不需要调用这个for循环,因为电梯在停靠时,就会判断一下方向,所以这个for循环是没有必要的。只需要在整个的move大循环中调用一次
nextFloor=getNextFloor(); elevator.setCurrentFloor(nextFloor);
停靠判断成功后增加一次方向判断即可。

其他测试用例
只使用PTA给出的测试用例是完全不够的,为此求助同学帮助下,网上找到如下的测试用例:

1
20
<5>
❤️,UP>
<7>
<5,UP>
<2>
<6,DOWN>
<16,DOWN>
<4,UP>
<14,UP>
<9>
<3>
<2,UP>
< 3,DOWN>
end

最开始的测试:陷入死等,卡在这:

image-7

后来发现其实就是少了个if的判断。也就是上面提到的。当没有同方向的楼层时,要即时反向。

太痛苦了😢,调半天,结果拿到合适的测试用例后,就知道🐛所在。
真是🔥了。

week2.5 改进建议

  • 补全注释: 为Controller、RequestQueue等核心类和determineDirection()、getClosest()等复杂方法添加注释,说明职责和逻辑规则(如同向优先条件),降低理解成本。
  • 简化嵌套: 拆分getClosest()中的 4 层嵌套,进一步分成小方法,每个方法只做一件事。

WEEK3

week3.1 类图设计

有现成的类图干嘛不用😆

image-8

week3.2 核心思路

第三次作业的核心进步在于引入了 Passenger 类作为统一的请求模型,同时把外部请求换成了楼层,其他很多内容没有太大变化。只要具体修改几个处理处理函数就可以。

  • void processRequests():这次外部请求的正则表达式要换一换。
  • determineDirection():这次要利用Passenger类的属性direction,来判断电梯的方向。
  • void move():没有太大变化。
  • boolean shouldStop(): 也没有太大变化,就是要注意外部请求判断时用srcFloor还是dstFloor。
  • Integer getNextFloor():每变化
  • Integer getClosest(Integer a,Integer b):每太大变化
  • void openDoor():根本没变😆
  • void removeRequests(int currentFloor):变化不大,增加一个内部请求和外部请求srcFloor相同的判断,出队外部请求后将dstFloor加入内部请求队列。

整体流程:
Controller 主导调度,协调Elevator、RequestQueue和Passenger

  1. 输入解析(Controller.processRequests ()):
    读取最小 / 最大楼层,初始化Elevator实例(默认状态STOPPED、方向IDLE);
    循环读取请求,通过正则解析并封装为Passenger对象:
    内部请求(格式<楼层>):创建Passenger(sourceFloor=null, destinationFloor=输入楼层);
    外部请求(格式<源楼层,目的楼层>):创建Passenger(sourceFloor=源楼层, destinationFloor=目的楼层);
    校验楼层合法性(源楼层 / 目的楼层需在[minFloor, maxFloor]范围内),调用RequestQueue的addInternalRequest/addExternalRequest将Passenger加入对应队列;
    输入 "end"(不区分大小写)终止输入。
  2. 调度启动(Controller.move ()):
    先调用determineDirection()确定初始运行方向(基于Passenger的sourceFloor/destinationFloor和当前楼层);
    输出初始楼层状态(Current Floor: 初始楼层 Direction: 方向);
    进入循环(只要内外队列非空):
    a. 停靠判断(Controller.shouldStop ()):检查当前楼层是否有需处理的Passenger:
    内部队首Passenger的destinationFloor等于当前楼层;
    外部队首Passenger的sourceFloor等于当前楼层,且其方向(Passenger.getDirection()推导)与电梯一致;
    电梯同向运行到 “最后一层”(无更远处请求),需处理当前楼层剩余请求;
    b. 若需停靠:
    输出 “Open Door # Floor 楼层数”→“Close Door”(通过flag保证一层只开一次门);
    调用removeRequests()处理请求:内部请求出队;外部请求出队后,将其destinationFloor对应的Passenger加入内部队列(外部→内部请求闭环);
    调用determineDirection()更新方向,设置电梯状态为MOVING;
    c. 若不需停靠:
    调用getNextFloor()计算下一层(UP加 1,DOWN减 1);
    更新当前楼层,输出移动状态(Current Floor: 下一层 Direction: 方向);
    d. 重复步骤 a-c,直至所有请求处理完毕。

week3.3 SourceMonitor分析报告

image-9

指标类别 具体数值/信息
代码行数 413
有效语句数 249
分支百分比 25.3%
函数调用语句数 96
注释比例 8.5%
类数量 7
方法数/类 5.71
方法平均语句数 4.78
最复杂方法 Controller.processRequests()
最大复杂度 10
最深嵌套行数 330
最大嵌套深度 7
平均嵌套深度 1.97
平均复杂度 1.59

分析

  1. 模型驱动架构,职责分离更彻底
    类数量=7,方法数/类=5.71 :第三次引入Passenger类作为统一请求模型,将外部请求的“源楼层→目的楼层”逻辑闭环到单一实体中,实现“外部请求处理后自动转为内部请求”的业务闭环。Elevator仅管物理状态、RequestQueue仅管双队列存储、Controller仅管调度决策,完全遵循单一职责原则,相比第二次的“请求类型割裂”,架构解耦更彻底。
  2. Passenger类降低逻辑冗余
    最复杂方法为Controller.processRequests(),最大复杂度=10,平均复杂度=1.59:processRequests()需处理“内部/外部请求的正则解析、Passenger对象封装、楼层合法性校验、队列添加”等逻辑,虽复杂度略高于第二次,但因Passenger模型统一了请求格式,实际逻辑冗余度显著降低;move()shouldStop()等核心调度方法因职责单一,平均复杂度仅1.59。
  3. 最深嵌套行=330
    getClosest()removeRequests()存在7层嵌套,逻辑层级过深,
  4. 函数调用语句数=96,分支百分比=25.3%
    函数调用增多说明逻辑被拆分为更多小方法(如Passenger.getDirection()Elevator.isValidFloor()),提升了代码复用性。

week3.4 踩坑心得

有了前两次的经验,这次代码很快就搞完了👍,只有一个坑,在逻辑问题上。

  • 多次的同层请求
    第二次的才可也提到,处理重复请求尽量在processRequests()中,避免在move()中处理,因为move()仅负责电梯移动,不应该处理业务逻辑。
    但这次由于外部请求的dstFloor也会加入内部请求队列,所以要在removeRequests()中判断是否与当前楼层相同。在原逻辑中,使用下面的测试用例:

    1
    20
    <5,15>
    <5,15>
    <5,16>
    <15>
    <15,8>
    end

在15层会多次调用openDoor(),因为会出现外部请求新加入15层的情况,而openDoor()会在shouldStop()中调用。所以,我增加了一个标志位,保证开门只开一次:

if(flag==true){openDoor();flag=false;
}

week3.5 改进建议

  • 补全注释,降低理解
    为Passenger、Controller等核心类添加类注释,说明职责(如Passenger:统一请求模型,封装源楼层 / 目的楼层);
    为determineDirection()、removeRequests()等复杂方法添加步骤注释,说明逻辑规则(如外部请求转内部请求的条件);
    关键变量(如flag、passenger1)补充用途说明,避免歧义。
  • 简化深层嵌套
    a. 拆分getClosest()(7 层嵌套):进一步拆成小方法,每个方法仅负责单一逻辑;
    b. 优化removeRequests()的嵌套条件:用局部变量替代复杂表达式(如isExternalRequestValid = passenger2 != null && passenger2.getSourceFloor() == currentFloor),降低阅读难度。
  • 简化深层嵌套
    所有请求处理完毕后,在move()循环结束前,将电梯方向设为IDLE、状态设为STOPPED,符合实际电梯行为。

3.总结

总算到这了😄,感觉写markdown比写代码还累💻📝

三次电梯调度作业的迭代,本质是从 “面向过程” 到 “面向对象”,从“逻辑堆砌”到“架构设计”的完整实践,每一步都踩在 “解耦、复用、可维护” 的核心诉求上,也让我对 “架构设计” 、“面向对象”等概念地理解从模糊变得清晰。

3.1 这些坑,踩了才懂

  • “先设计,后编码” 不是一句空话
    第一次没画类图,写代码时 “想到哪写到哪”,结果Elevator类成了 “万能容器”;第二次直接用题目给的类图,代码结构清晰,甚至能 “按图索骥” 猜方法作用 —— 这才明白,类图不是 “多余的步骤”,而是 “避免返工的地图”,它能提前梳理清楚 “谁该做什么”,减少后续逻辑缠绕。

  • 单一职责原则是 “解耦的钥匙”
    最开始觉得 “一个类多做几件事没关系”,比如第一次的Elevator又管移动又管调度;后来发现,“职责越单一,代码越抗造”—— 比如RequestQueue只负责 “加请求、取请求”,不管调度逻辑;Passenger只负责 “封装请求信息”,不管怎么处理 —— 这样修改一个类时,不用担心影响其他模块,调试时也能快速定位问题(比如 “请求加不进队列” 只需要查RequestQueue,不用翻调度逻辑)。

  • 测试用例是救星”
    第一次只依赖 PTA 的测试用例,结果 “看似能跑,实则有坑”;第二次和第三次主动找同学要测试用例,甚至自己构造 “极端场景”(比如同层多个请求、反向请求叠加),才发现了 “超时问题”“重复开门问题”—— 这才明白,“代码跑通只是第一步,覆盖更多场景才叫‘稳健’”,测试用例能帮你提前暴露 “隐藏的逻辑漏洞”。

  • 交流讨论,避免思维死胡同
    最开始写代码时,“思路清晰”,但 “实现起来” 却容易 “跑偏”。这也体现了软件设计的难点,“需求变更” 是 “不可避免” 的,“交流讨论” 是 “及时反馈” 的 “重要手段”。
    第二次作业时,如果不是同学给定测试用例,可能真的写不出来。

  • 合理使用AI
    不可否认,AI确实强。
    但是如果直接把整个代码给AI,如DeepSeek很容易陷入自己的思考,添油加醋。比如本次的大作业的LOOK算法只用比较两个队首的楼层,就可以确定电梯移动方向,而不需要遍历整个队列。DeepSeek等AI工具完全无法理解,甚至让它改错还是会出现我说我的,他按照自己的想法修改。
    但是,AI强在找bug,比如我的while循环哪个条件写的不对,AI能及时发现并修正;再比如AI记忆力强,有时候不熟悉的Java语法,如正则表达式怎么写,让AI指出错误会很快。
    不要指望AI会设计,因为具体的需求还是要大脑根据题意来理解,而他们只是实现设计过程中的工具。

3.2 “大作业”还多,慢慢来
虽然三次作业有进步,但还有很多 “优化空间”:

  • 注释要 “够意思”:三次作业的注释比例都不高(最高 12.4%),复杂方法(比如getClosest())没有步骤注释,后来自己回头看代码,都要 “重新推导逻辑”—— 好注释不是 “越多越好”,而是 “关键逻辑说清楚”,比如 “为什么这里要判断‘同向最后一层’”,一句话就能帮自己或别人省很多时间。
  • 嵌套要 “浅一点”:第三次的getClosest()有 7 层嵌套,看起来像 “逻辑迷宫”;其实可以拆成小方法,比如hasSameDirectionRequest()(判断同向请求)、calculateMinDistance()(计算最近距离),每个方法只做一件事,嵌套深度自然降下来,代码也更易读。

OK了,第一次的Blog就到这!
return 0;
😉❤️😆

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/972061.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

质量管理数字化(QMS系统)实施指南‌

一、QMS定义:软件与体系的区分 在探讨如何开展之前,需厘清QMS的定义。质量行业人员通常理解的QMS为质量管理体系(Quality Management System),而本文聚焦于工业软件领域的质量管理软件(Quality Management Softw…

g for linux 下载

在 Linux 系统中,下载文件通常使用 wget 或 curl 工具。以下是两种常用的方法:? 方法 1:使用 wget 下载文件wget https://example.com/file.txtwget 是一个命令行下载工具,支持 HTTPS、FTP、HTTP 等多种协议。htt…

2025针阀式热流道厂家一览:技术特色与应用优势

2025针阀式热流道厂家一览:技术特色与应用优势。针阀式热流道系统凭借无浇口痕迹、高成型一致性等特点,在精密注塑领域占据重要地位。市场上有多家专注于针阀式热流道研发生产的厂家,以下推荐几家表现突出的企业,其…

g linux

您提到的“g linux”可能是输入错误或不完整。如果您是想询问与 Linux 系统 相关的问题,我将非常乐意为您提供帮助。请具体说明您想了解的内容,例如:Linux 命令行操作Shell 脚本编写系统管理(如文件系统、进程管理…

2025国内喷码机厂家排名综合实力榜

2025国内喷码机厂家排名综合实力榜。国内喷码机市场经过多年发展,已涌现出一批技术成熟、服务完善的实力厂家。这些厂家凭借对本土行业需求的深刻理解,在设备性能、应用适配与售后服务等方面形成了独特优势。以下结合…

fuse linux

当然可以!fuse(Filesystem in Userspace)是一个非常强大的工具,它允许你在不使用传统的文件系统(如ext4、xfs等)的情况下,在Linux系统上创建自定义的文件系统。fuse 是通过 fuse 模块实现的,它允许用户编写自己…

【迅为工业RK3568稳定可靠】itop-3568开发板Linux驱动开发实战:RK3568内核模块符号导出详解

【迅为工业RK3568稳定可靠】itop-3568开发板Linux驱动开发实战:RK3568内核模块符号导出详解【迅为工业RK3568稳定可靠】itop-3568开发板Linux驱动开发实战:RK3568内核模块符号导出详解选择迅为iTOP-3568开发板,获取…

虚幻基础:行为树 - 指南

虚幻基础:行为树 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &q…

集成Win10+Win11优化工具 Windows Manager v2.2.1 绿色便携版!C盘经常红温清理方法

简介 Windows Manager中文激活版(Windows优化大师)是一款集Windows10/11所有功能于一身的Win10/11系统优化工具,这款系统优化软件提供40多个实用程序来优化,调整,清理,加速和修复Windows 10/11,可以让系统运行流畅,解决…

C语言`FILE`结构体 与 Python文件对象 的对比

对比维度 C语言FILE结构体 Python文件对象 为什么本质不同?模式字符串 "r", "w", "a", "r+", "w+", "a+", "rb", "wb", "ab&…

2025质量可靠的义乌刺绣工厂推荐下,厂家品质深度分析

2025质量可靠的义乌刺绣工厂推荐下,厂家品质深度分析。义乌及周边地区的刺绣工厂中,“质量可靠” 是商家合作的核心诉求。这不仅体现在产品的耐用性上,更涵盖工艺稳定性、材质安全性与品控严谨性。以下推荐的六家工…

2025 11月十大靠谱启闭机品牌盘点推荐,螺杆启闭机、卷扬启闭机、手动启闭机、手电两用启闭机 优势及应用分析

启闭机作为水利工程的核心设备,直接关系到工程安全与运行效率。选择时需优先明确需求:按类型可聚焦螺杆启闭机、卷扬启闭机、手动启闭机、手电两用启闭机等核心品类,按配套需求可搭配铸铁启闭机闸门、启闭机拍门等产…

推荐几家靠谱的刺绣厂家电话,2025刺绣厂家实力解析

推荐几家靠谱的刺绣厂家电话,2025刺绣厂家实力解析。在刺绣行业中,“靠谱” 体现在工艺扎实、服务规范与信誉良好等多个方面。以下推荐的六家刺绣厂家均经过市场验证,其中浦江县俊贤刺绣有限公司以突出的工艺优势位…

虚拟机共享文件夹实现自动挂载

1. sudo vim /etc/fstab编辑文件 2. 添加 ".host:/ /mnt/hgfs fuse.vmhgfs-fuse allow_other,defaults 0 0" 3. sudo mount -a重新挂载

目标检测算法——R-CNN系列

R-CNN 系列算法是深度学习目标检测领域发展的关键历程,标志着该领域从传统方法转向深度学习的转变。 以下是 R-CNN、Fast R-CNN 和 Faster R-CNN 三个核心模型的总结和对比,以及对 Mask R-CNN 的简单提及:🚀 R-CN…

如何助力质量人员提高工作效率与绩效—供应商质量评审

引言:破解多行业适配的数字化难题‌ 在质量管理数字化浪潮中,一个核心问题持续引发行业深思:‌如何通过单一SaaS产品满足千差万别的行业需求?‌ 云质QMS面对来自健身器材、化工、汽车、新能源电池等截然不同的制造…

每周读书与学习-JMeter性能测试脚本编写实战(一)-如何实现用户需先登录,然后再请求别的接口

每周读书与学习是由清华大学出版社出版的《JMeter核心技术、性能测试与性能分析》一书的作者推出,分享作者多年的IT从业经历,希望对很多计算机科学技术IT类专业毕业生以及IT从业者有所帮助。 在前面的学习中,介绍了…

详细介绍:【iOS】自动引用计数(一)

详细介绍:【iOS】自动引用计数(一)2025-11-21 13:21 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !i…

时序数据库选型指南:为什么TDengine正在成为行业标准

在物联网(IoT)、工业互联网(IIoT)、IT运维和金融科技等领域,时序数据正以前所未有的速度增长。面对海量的设备指标、传感器数据和监控日志,选择一个合适的时序数据库(Time-Series Database, TSDB)已成为系统架…

专业的技术文档 | Apache Pulsar 如何满足金融级的容灾场景

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …