我的第一次博客作业
一:前言:
学习Java语言也快三个月了,就在我认为还可以像对付C语言那样处理Java课时,三次大题量的电梯类题目却直接将我“击破”,从此刻开始我才认识到两种语言学习的不同,我需要更多的信心与练习。在这三次作业里,每个题目不同的类的设计与方法的处理都十分考验我们的编程能力。从此,编程世界的另一扇大门已缓缓开启,正等待着我们逐步探索..
二:代码设计与分析:
--第五次作业:
点击查看代码
import java.util.Scanner;
class Elevator {
private int minFloor;
private int maxFloor;
private int currentFloor;
private String direction;
private String state;
private Queue<Integer> internalRequests;
private Map<Integer, List<String>> externalUpRequests;
private Map<Integer, List<String>> externalDownRequests;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = minFloor;
this.direction = "STILL";
this.state = "STOP";
this.internalRequests = new PriorityQueue<>();
this.externalUpRequests = new HashMap<>();
this.externalDownRequests = new HashMap<>();
}
public void addInternalRequest(int floor) {
if (isValidFloor(floor)) {
internalRequests.add(floor);
} else {
System.out.println("无效的楼层请求: " + floor);
}
}
private boolean isValidFloor(int floor) {
return floor >= minFloor && floor <= maxFloor;
}
public void run() {
while (!internalRequests.isEmpty() || !externalUpRequests.isEmpty() || !externalDownRequests.isEmpty()) {
if (direction.equals("STILL")) {
if (!internalRequests.isEmpty()) {
direction = internalRequests.peek() > currentFloor ? "UP" : "DOWN";
} else if (!externalUpRequests.isEmpty()) {
int nextUpFloor = Collections.min(externalUpRequests.keySet());
direction = nextUpFloor > currentFloor ? "UP" : "DOWN";
} else if (!externalDownRequests.isEmpty()) {
int nextDownFloor = Collections.max(externalDownRequests.keySet());
direction = nextDownFloor > currentFloor ? "UP" : "DOWN";
}
}
state = "MOVING";
if (direction.equals("UP")) {
while (currentFloor < maxFloor) {
currentFloor++;
printCurrentFloor();
if (shouldStop()) {
stopAndHandleRequests();
}
if (internalRequests.isEmpty() && externalUpRequests.isEmpty()) {
direction = "DOWN";
break;
}
}
} else if (direction.equals("DOWN")) {
while (currentFloor > minFloor) {
currentFloor--;
printCurrentFloor();
if (shouldStop()) {
stopAndHandleRequests();
}
if (internalRequests.isEmpty() && externalDownRequests.isEmpty()) {
direction = "UP";
break;
}
}
}
}
state = "STOP";
direction = "STILL";
}
private void printCurrentFloor() {
System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
}
private boolean shouldStop() {
return internalRequests.contains(currentFloor) || externalUpRequests.containsKey(currentFloor) || externalDownRequests.containsKey(currentFloor);
}
private void stopAndHandleRequests() {
state = "OPENING";
System.out.println("Open Door # Floor " + currentFloor);
internalRequests.remove(currentFloor);
externalUpRequests.remove(currentFloor);
externalDownRequests.remove(currentFloor);
state = "CLOSING";
System.out.println("Close Door");
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int minFloor = scanner.nextInt();
int maxFloor = scanner.nextInt();
scanner.nextLine();
Elevator elevator = new Elevator(minFloor, maxFloor);
String input;
while (!(input = scanner.nextLine().trim()).equalsIgnoreCase("end")) {
if (input.startsWith("<") && input.endsWith(">")) {
input = input.substring(1, input.length() - 1);
if (input.contains(",")) {
String[] parts = input.split(",");
int floor = Integer.parseInt(parts[0]);
String direction = parts[1];
elevator.addExternalRequest(floor, direction);
} else {
int floor = Integer.parseInt(input);
elevator.addInternalRequest(floor);
}
}
}
elevator.run();
}
}
类图:
复杂度分析: .
以下是对图片内容的解读:
行数:118 行
语句数:88 条
分支语句百分比:21.6%
方法调用语句数:50 条
注释行百分比:0.0% ,代码无任何注释
类和接口数量:2 个
每个类的平均方法数:4.00 个
每个方法的平均语句数):11.64 条
最复杂方法的行号:Elevator.run() ,位于 34 行
最大复杂度为21,方法是Elevator.run()
平均复杂度:4.75
最深代码块行号:53 行
最大代码块深度为 6
平均代码块深度:2.84
----以下是对我代码的总结分析:
①我注意到自己在代码注释方面严重缺失,注释行百分比为 0.0 。这使得代码就像一本没有目录和注解的随手。②,整体代码的语句较多,复杂度残次不齐,调用较为混乱。尤其Elevator.run() 方法的最大复杂度达到了 21 ,远远超出合理范围,而且此方法承担了太多职责,可维护性与扩展性大打折扣。③仅有 2 个类和接口,分支逻辑较为复杂,容易遗漏边界条件。④最大代码块深度为 6 ,平均代码块深度也有 2.84,说明代码中存在大量的嵌套结构,例如循环中嵌套条件判断,条件判断中又嵌套其他逻辑等。这种深层嵌套使得代码缩进过多,视觉上难以快速定位和理解逻辑关系,也增加了出错的概率。 这次作业让我明白:不能只局限于简单的代码操作,对更多需求、类的分析才能不断增强我的编程能力。
**--第六次作业:**
点击查看代码
import java.util.Scanner;
class Elevator {
private int minFloor;
private int maxFloor;
private int currentFloor;
private String direction;
private String state;
private Queue<Integer> internalRequests;
private Map<Integer, List<String>> externalUpRequests;
private Map<Integer, List<String>> externalDownRequests;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = minFloor;
this.direction = "STILL";
this.state = "STOP";
this.internalRequests = new PriorityQueue<>();
this.externalUpRequests = new HashMap<>();
this.externalDownRequests = new HashMap<>();
}
private boolean isValidFloor(int floor) {
return floor >= minFloor && floor <= maxFloor;
}
public void run() {
while (!internalRequests.isEmpty() || !externalUpRequests.isEmpty() || !externalDownRequests.isEmpty()) {
if (direction.equals("STILL")) {
if (!internalRequests.isEmpty()) {
direction = internalRequests.peek() > currentFloor ? "UP" : "DOWN";
} else if (!externalUpRequests.isEmpty()) {
int nextUpFloor = Collections.min(externalUpRequests.keySet());
direction = nextUpFloor > currentFloor ? "UP" : "DOWN";
} else if (!externalDownRequests.isEmpty()) {
int nextDownFloor = Collections.max(externalDownRequests.keySet());
direction = nextDownFloor > currentFloor ? "UP" : "DOWN";
}
}
state = "MOVING";
if (direction.equals("UP")) {
while (currentFloor < maxFloor) {
currentFloor++;
printCurrentFloor();
if (shouldStop()) {
stopAndHandleRequests();
}
if (internalRequests.isEmpty() && externalUpRequests.isEmpty()) {
direction = "DOWN";
break;
}
}
} else if (direction.equals("DOWN")) {
while (currentFloor > minFloor) {
currentFloor--;
printCurrentFloor();
if (shouldStop()) {
stopAndHandleRequests();
}
if (internalRequests.isEmpty() && externalDownRequests.isEmpty()) {
direction = "UP";
break;
}
}
}
}
state = "STOP";
direction = "STILL";
}
private void printCurrentFloor() {
System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
}
private boolean shouldStop() {
return internalRequests.contains(currentFloor) || externalUpRequests.containsKey(currentFloor) || externalDownRequests.containsKey(currentFloor);
}
private void stopAndHandleRequests() {
state = "OPENING";
System.out.println("Open Door # Floor " + currentFloor);
internalRequests.remove(currentFloor);
externalUpRequests.remove(currentFloor);
externalDownRequests.remove(currentFloor);
state = "CLOSING";
System.out.println("Close Door");
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int minFloor = scanner.nextInt();
int maxFloor = scanner.nextInt();
scanner.nextLine();
Elevator elevator = new Elevator(minFloor, maxFloor);
String input;
while (!(input = scanner.nextLine().trim()).equalsIgnoreCase("end")) {
if (input.startsWith("<") && input.endsWith(">")) {
input = input.substring(1, input.length() - 1);
if (input.contains(",")) {
String[] parts = input.split(",");
int floor = Integer.parseInt(parts[0]);
String direction = parts[1];
elevator.addExternalRequest(floor, direction);
} else {
int floor = Integer.parseInt(input);
elevator.addInternalRequest(floor);
}
}
}
elevator.run();
}
}
类图:
复杂度分析: 
以下是对图片内容的解读:
行数: 109行
语句数: 83条
分支语句百分比:20.5%
方法调用语句数:47 条
注释行百分比:0.0% ,代码无任何注释
类和接口数量:2个
每个类的平均方法数: 3.50个
每个方法的平均语句数: 9.29条
最复杂方法的行号:26,Elevator.run()
最大复杂度为21,方法也是Elevator.run()
平均复杂度:5.00
最深代码块行号:行
最大代码块深度为 :6
平均代码块深度:2.88
这次代码的不足:
①同样的,这次代码也没有用任何注释,可读性不高。②最大代码块深度为 6,平均代码块深度为 2.88 。不仅使代码缩进过多,视觉上难以理解,还容易在逻辑判断时出错,影响代码的正确性和可维护性。③整体方法调用语句数有 47 条,方法间调用频繁。虽体现了模块化,但可能存在不必要的调用或调用层次过深,导致代码结构混乱,难以理清方法间的依赖关系和执行顺序。 综上,出现的问题很多在第五次题目集中也出现了,代表我对题目的理解仍然不到位,代码没有明显改进。在这方面还有待提高。
**第七次题目:**
点击查看代码
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 乘客类
class Passenger {
private int sourceFloor;
private int destinationFloor;
public Passenger(int sourceFloor, int destinationFloor) {
this.sourceFloor = sourceFloor;
this.destinationFloor = destinationFloor;
}
public int getSourceFloor() {
return sourceFloor;
}
public int getDestinationFloor() {
return destinationFloor;
}
}
// 队列类
class Queue {
private List<Integer> internalQueue;
private List<Passenger> externalQueue;
public Queue() {
internalQueue = new ArrayList<>();
externalQueue = new ArrayList<>();
}
public boolean isExternalQueueEmpty() {
return externalQueue.isEmpty();
}
public boolean isInternalQueueEmpty() {
return internalQueue.isEmpty();
}
public void addExternalRequest(Passenger passenger) {
externalQueue.add(passenger);
}
public void addInternalRequest(int floor) {
if (!internalQueue.contains(floor)) {
internalQueue.add(floor);
}
}
public Passenger getNextExternalPassenger() {
return externalQueue.get(0);
}
public Passenger removeNextExternalPassenger() {
return externalQueue.remove(0);
}
public List<Integer> getInternalQueue() {
return internalQueue;
}
}
// 电梯类
class Elevator {
private int minFloor;
private int maxFloor;
private int currentFloor;
private String direction;
private Queue queue;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = minFloor;
this.direction = "UP";
this.queue = new Queue();
}
public void addExternalRequest(Passenger passenger) {
queue.addExternalRequest(passenger);
}
public void addInternalRequest(int floor) {
queue.addInternalRequest(floor);
}
public void processRequests() {
while (!queue.isExternalQueueEmpty() || !queue.isInternalQueueEmpty()) {
int nextFloor;
if (queue.isExternalQueueEmpty()) {
nextFloor = getNextInternalFloor();
} else {
Passenger nextPassenger = queue.getNextExternalPassenger();
nextFloor = nextPassenger.getSourceFloor();
}
while (currentFloor != nextFloor) {
if (currentFloor < nextFloor) {
currentFloor++;
direction = "UP";
} else {
currentFloor--;
direction = "DOWN";
}
System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
}
if (!queue.isExternalQueueEmpty() && queue.getNextExternalPassenger().getSourceFloor() == currentFloor) {
Passenger passenger = queue.removeNextExternalPassenger();
System.out.println("Open Door # Floor " + currentFloor);
System.out.println("Close Door");
addInternalRequest(passenger.getDestinationFloor());
}
if (queue.getInternalQueue().contains(currentFloor)) {
System.out.println("Open Door # Floor " + currentFloor);
System.out.println("Close Door");
queue.getInternalQueue().remove((Integer) currentFloor);
}
}
}
private int getNextInternalFloor() {
if (direction.equals("DOWN")) {
int min = Integer.MAX_VALUE;
for (int floor : queue.getInternalQueue()) {
if (floor < min) {
min = floor;
}
}
return min;
} else {
int max = Integer.MIN_VALUE;
for (int floor : queue.getInternalQueue()) {
if (floor > max) {
max = floor;
}
}
return max;
}
}
}
// 控制类
class ElevatorController {
private Elevator elevator;
public ElevatorController(int minFloor, int maxFloor) {
this.elevator = new Elevator(minFloor, maxFloor);
}
public void processInput() {
Scanner scanner = new Scanner(System.in);
int minFloor = scanner.nextInt();
int maxFloor = scanner.nextInt();
scanner.nextLine(); // 消耗掉换行符
while (true) {
String request = scanner.nextLine().trim();
if (request.equalsIgnoreCase("end")) {
break;
}
if (request.startsWith("<") && request.endsWith(">")) {
request = request.substring(1, request.length() - 1);
if (request.contains(",")) {
String[] parts = request.split(",");
int sourceFloor = Integer.parseInt(parts[0]);
int destinationFloor = Integer.parseInt(parts[1]);
Passenger passenger = new Passenger(sourceFloor, destinationFloor);
elevator.addExternalRequest(passenger);
} else {
int floor = Integer.parseInt(request);
elevator.addInternalRequest(floor);
}
}
}
elevator.processRequests();
scanner.close();
}
}
// 主类
public class ElevatorScheduling {
public static void main(String[] args) {
ElevatorController controller = new ElevatorController(1, 20);
controller.processInput();
}
}
类图:
复杂度分析: 
图片内容解读如下:
行数: 190行
语句数: 113条
分支语句百分比:17.7%
方法调用语句数:49 条
注释行百分比:3.2%
类和接口数量:1个
每个类的平均方法数: 19.00个
每个方法的平均语句数: 5.63条
最复杂方法的行号:181, Main.main()
最大复杂度为1,方法也是Main.main()
平均复杂度:1
最深代码块行号:98行
最大代码块深度为 :4
平均代码块深度:1.54
在这次的题目里,我添加了适量的注释,以保证最基本的可读性。内部请求用优先队列、外部请求用映射区分上下行,能高效处理不同类型请求,提升电梯调度效率。但还是有一些不足的地方:①电梯调度策略相对简单,未考虑如高峰时段调度、多电梯协同等复杂场景;代码中一些固定参数(如楼层范围在主函数硬编码),不利于灵活调整和扩展功能。②单个类方法数过多(每个类平均 19 个方法 ),可能导致类职责不够单一,影响代码可维护性与复用性。
三--踩坑心得、
开发电梯调度程序时,我收获不少经验教训。起初,代码结构设计虽有一定条理,按功能分了类,可实际操作才发现注释太少,后期回看代码,好多逻辑都得重新梳理,理解成本大增。输入处理这块也掉坑里了,没做异常处理,根本没考虑用户输错数据咋办,程序一下就崩了。还有,以为简单的调度策略够用,结果发现应对不了复杂场景,比如早晚高峰。另外,方法数量在类里分布不合理,一个类塞太多方法,职责混乱。这次经历让我明白,写代码不能只图功能实现,注释、健壮性、扩展性这些都得兼顾,才能编出高质量的程序。
例图:
四--总结:
本次开发的电梯调度程序,通过 Java 语言实现了基本的电梯调度功能。代码整体采用面向对象设计,将不同功能封装在不同类中,如 Passenger 类存储乘客信息,Elevator 类负责电梯运行逻辑,ElevatorController 类处理用户输入,结构较为清晰,便于维护和扩展。
然而,代码仍存在一些不足之处,需要进一步学习和研究。首先,注释过少,这严重影响了代码的可读性和可维护性。后续需要养成良好的注释习惯,详细解释关键逻辑和方法的用途。其次,异常处理方面存在缺失,程序在面对非法输入或运行时异常时较为脆弱。应学习如何完善异常处理机制,增强程序的健壮性。
在扩展性上,当前的调度策略较为简单,难以应对复杂的实际场景,如多电梯协同调度、高峰时段优化等。这需要深入研究更高级的算法和策略,以优化电梯调度效率。此外,代码的复杂度分布不均衡,单个类中的方法数量过多,经常违反单一职责原则。需要进一步学习设计模式,合理拆分功能,使代码结构更加合理。
总体而言,本次开发是一次宝贵的实践经验,通过不断学习和改进,有望使程序更加完善和实用。
同时希望老师上课的方式可以更生动些,实验要求可以简洁些。