电梯程序总结blog
一、前言
第一阶段的Java大作业这三次题目集层层迭代,于我而言是很大的挑战,考察了我的题目理解能力、逻辑思维以及类设计。不仅大大促进了我对Java语法的适应,也让我对面向对象编程有了初步的了解,积累了宝贵的实战经验。
二、 设计与分析
第一次题目集
点击查看代码
import java.util.Scanner;
import java.util.LinkedList;
import java.util.Queue;
class Elevator {
private int minFloor, maxFloor, currentFloor;
private String direction, state;
private Queue<Integer> internalRequests;
private Queue<Integer> externalRequests;
private Queue<String> externalRequestsDir;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = minFloor;
this.direction = "IDLE";
this.state = "STOP";
this.internalRequests = new LinkedList<>();
this.externalRequests = new LinkedList<>();
this.externalRequestsDir = new LinkedList<>();
}
public void addIn(int f) {
internalRequests.add(f);
}
public void addOut(int f, String dir) {
externalRequests.add(f);
externalRequestsDir.add(dir);
}
public void run() {
while (!(internalRequests.isEmpty() && externalRequests.isEmpty())) {
if (state.equals("STOP")) {
determine();
}
if (direction.equals("UP")) {
currentFloor++;
System.out.printf("Current Floor: %d Direction: UP\n", currentFloor);
}
if (direction.equals("DOWN")) {
currentFloor--;
System.out.printf("Current Floor: %d Direction: DOWN\n", currentFloor);
}
judge();
}
}
public void determine() {
if (direction.equals("IDLE")) {
if (!externalRequests.isEmpty()) direction = "UP";
state = "MOVE";
System.out.printf("Current Floor: %d Direction: UP\n", currentFloor);
}
else if (direction.equals("UP")) {
if (!internalRequests.isEmpty()) {
if (internalRequests.element() > currentFloor) {
state = "MOVE";
}
else {
if (externalRequests.isEmpty()) {
state = "MOVE";
direction = "DOWN";
}
else {
int m = parseFloor(externalRequests.peek());
if (m > currentFloor) state = "MOVE";
else {
state = "MOVE";
direction = "DOWN";
}
}
}
}
if (internalRequests.isEmpty()) {
int m = parseFloor(externalRequests.peek());
if (m > currentFloor) state = "MOVE";
else {
state = "MOVE";
direction = "DOWN";
}
}
}
else if (direction.equals("DOWN")) {
if (!internalRequests.isEmpty()) {
if (internalRequests.element() < currentFloor) {
state = "MOVE";
}
else {
if (externalRequests.isEmpty()) {
state = "MOVE";
direction = "UP";
}
else {
int m = parseFloor(externalRequests.peek());
if (m < currentFloor) state = "MOVE";
else {
state = "MOVE";
direction = "UP";
}
}
}
}
if (internalRequests.isEmpty()) {
int m = parseFloor(externalRequests.peek());
if (m < currentFloor) state = "MOVE";
else {
state = "MOVE";
direction = "UP";
}
}
}
}
private int parseFloor(int floor) {
return floor;
}
public void judge() {
int t = 0;
if (!internalRequests.isEmpty()) {
if (internalRequests.element() == currentFloor) {
internalRequests.remove();
t = 1;
}
if (!externalRequests.isEmpty()) {
int m = parseFloor(externalRequests.peek());
if (m == currentFloor) {
if (externalRequestsDir.peek().equals(direction)) {
externalRequests.remove();
externalRequestsDir.remove();
t = 1;
}
else {
if (!internalRequests.isEmpty()) {
if ((direction.equals("UP") && internalRequests.element() < currentFloor) ||
(direction.equals("DOWN") && internalRequests.element() > currentFloor)) {
externalRequests.remove();
externalRequestsDir.remove();
t = 1;
}
}
}
}
}
}
else {
if (!externalRequests.isEmpty()) {
int m = parseFloor(externalRequests.peek());
if (m == currentFloor) {
externalRequests.remove();
externalRequestsDir.remove();
t = 1;
}
}
}
if (t == 1) {
System.out.printf("Open Door # Floor %d\n", currentFloor);
System.out.printf("Close Door\n");
state = "STOP";
}
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int min = scanner.nextInt();
int max = scanner.nextInt();
scanner.nextLine();
Elevator elevator = new Elevator(min, max);
while (true) {
String request = scanner.nextLine();
if (request.equalsIgnoreCase("end")) break;
else {
if (request.matches("<\\d+>")) {
int floor = Integer.parseInt(request.substring(1, request.length()-1));
elevator.addIn(floor);
}
else if (request.matches("<\\d,UP>")) {
int floor = Integer.parseInt(request.substring(1, request.indexOf(',')));
elevator.addOut(floor, "UP");
}
else if (request.matches("<\\d+,DOWN>")) {
int floor = Integer.parseInt(request.substring(1, request.indexOf(',')));
elevator.addOut(floor, "DOWN");
}
}
}
elevator.run();
scanner.close();
}
}
类图:

类设计:
- Elevator类:设计了电梯的最小楼层数(默认为1层)、最大楼层数、当前楼层、运行方向、运行状态等属性,以及储存内部请求楼层数的链表,储存外部请求楼层数的链表,储存外部请求方向的链表。功能有向内部链表末尾加入节点(addIn),向外部链表末尾加入节点(addOut),判断方向(determine),运行(run),需要在当前楼层停靠并开关门(judge)等
- Main类:主要使用正则表达式将读入的数据进行处理
点击查看SourceMontor的生成报表内容


分析与心得:
- 方向判断逻辑复杂:determine方法中多层嵌套的if-else语句用于判断电梯方向,代码可读性较差,且在处理内外请求优先级时逻辑不够清晰。
- 请求匹配策略单一:judge方法仅简单判断当前楼层是否存在请求,未考虑同向请求优先处理的原则,可能导致电梯频繁改变方向,降低运行效率。
- 方法职责不单一:determine方法同时承担方向判断和状态切换逻辑,违反单一职责原则;judge方法将请求匹配与开关门操作耦合,增加了维护成本。
第二次题目集
点击查看代码
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int minfloor = scanner.nextInt();
int maxfloor = scanner.nextInt();
Elevator elevator = new Elevator(minfloor, maxfloor);
RequestQueue requestQueue = new RequestQueue().getQueueInstance(scanner, elevator.getMinFloor(), elevator.getMaxFloor());
Controller controller = new Controller(elevator, requestQueue);
controller.processRequests();
}
}
class RequestQueue {
private LinkedList<Integer> internalRequests = new LinkedList<>();
private LinkedList<ExternalRequest> externalRequests = new LinkedList<>();
public RequestQueue() {
}
public RequestQueue getQueueInstance(Scanner scanner, int minFloor, int maxFloor) {
RequestQueue requestQueue = new RequestQueue();
while (scanner.hasNextLine()) {
String request = scanner.nextLine().trim();
if (request.equalsIgnoreCase("end")) {
break;
}
if (!request.isEmpty()) {
if (request.matches("<\\d+>")) {
int floor = Integer.parseInt(request.substring(1, request.length() - 1));
if (isValidFloor(floor, minFloor, maxFloor)) {
requestQueue.addInternalRequest(floor);
}
} else if (request.matches("<\\d+,UP>")) {
int floor = Integer.parseInt(request.substring(1, request.indexOf(',')));
if (isValidFloor(floor, minFloor, maxFloor)) {
requestQueue.addExternalRequest(floor, Direction.UP);
}
} else if (request.matches("<\\d+,DOWN>")) {
int floor = Integer.parseInt(request.substring(1, request.indexOf(',')));
if (isValidFloor(floor, minFloor, maxFloor)) {
requestQueue.addExternalRequest(floor, Direction.DOWN);
}
}
}
}
return requestQueue;
}
private boolean isValidFloor(int floor, int minFloor, int maxFloor) {
return floor >= minFloor && floor <= maxFloor;
}
public LinkedList<Integer> getInternalRequests() {
return internalRequests;
}
public void setInternalRequests(LinkedList<Integer> internalRequests) {
this.internalRequests = internalRequests;
}
public LinkedList<ExternalRequest> getExternalRequests() {
return externalRequests;
}
public void setExternalRequests(LinkedList<ExternalRequest> externalRequests) {
this.externalRequests = externalRequests;
}
void addInternalRequest(int floor) {
internalRequests.add(floor);
}
void addExternalRequest(int floor, Direction direction) {
externalRequests.add(new ExternalRequest(floor, direction));
}
}
class Controller {
private Elevator elevator;
private RequestQueue queue;
public Controller() {
}
public Controller(Elevator elevator, RequestQueue queue) {
this.elevator = elevator;
this.queue = queue;
}
public Elevator getElevator() {
return elevator;
}
public void setElevator(Elevator elevator) {
this.elevator = elevator;
}
public RequestQueue getQueue() {
return queue;
}
public void setQueue(RequestQueue queue) {
this.queue = queue;
}
public void processRequests() {
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: UP");
while (!queue.getInternalRequests().isEmpty() || !queue.getExternalRequests().isEmpty()) {
determineDirection();
move();
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
if (shouldStop(elevator.getCurrentFloor())) {
openDoors();
removeRequests(elevator.getCurrentFloor());
}
}
elevator.setState(State.STOPPED);
}
private void determineDirection() {
if (elevator.getDirection() == Direction.IDLE) {
if (!queue.getExternalRequests().isEmpty()) {
elevator.setDirection(Direction.UP);
}
elevator.setState(State.MOVING);
return;
}
if (!queue.getInternalRequests().isEmpty()) {
int internalFirst = queue.getInternalRequests().peek();
if (elevator.getDirection() == Direction.UP) {
if (internalFirst <= elevator.getCurrentFloor()) {
if (queue.getExternalRequests().isEmpty()) {
elevator.setDirection(Direction.DOWN);
} else {
int externalFirst = queue.getExternalRequests().peek().getFloor();
if (externalFirst <= elevator.getCurrentFloor()) {
elevator.setDirection(Direction.DOWN);
}
}
}
} else if (elevator.getDirection() == Direction.DOWN) {
if (internalFirst >= elevator.getCurrentFloor()) {
if (queue.getExternalRequests().isEmpty()) {
elevator.setDirection(Direction.UP);
} else {
int externalFirst = queue.getExternalRequests().peek().getFloor();
if (externalFirst >= elevator.getCurrentFloor()) {
elevator.setDirection(Direction.UP);
}
}
}
}
} else {
if (!queue.getExternalRequests().isEmpty()) {
int externalFirst = queue.getExternalRequests().peek().getFloor();
if (elevator.getDirection() == Direction.UP && externalFirst <= elevator.getCurrentFloor()) {
elevator.setDirection(Direction.DOWN);
} else if (elevator.getDirection() == Direction.DOWN && externalFirst >= elevator.getCurrentFloor()) {
elevator.setDirection(Direction.UP);
}
}
}
}
private void move() {
elevator.setState(State.MOVING);
int nextFloor = getNextFloor();
if (elevator.isValidFloor(nextFloor)) {
elevator.setCurrentFloor(nextFloor);
}
}
private boolean shouldStop(int floor) {
if (!queue.getInternalRequests().isEmpty() && queue.getInternalRequests().peek() == floor) {
return true;
}
if (!queue.getExternalRequests().isEmpty()) {
ExternalRequest firstExternal = queue.getExternalRequests().peek();
if (firstExternal.getFloor() == floor) {
if (firstExternal.getDirection() == elevator.getDirection()) {
return true;
}
if (queue.getInternalRequests().isEmpty()) {
return true;
}
if ((elevator.getDirection() == Direction.UP && queue.getInternalRequests().peek() < floor) ||
(elevator.getDirection() == Direction.DOWN && queue.getInternalRequests().peek() > floor)) {
return true;
}
}
}
return false;
}
private int getNextFloor() {
if (elevator.getDirection() == Direction.UP) {
return elevator.getCurrentFloor() + 1;
} else if (elevator.getDirection() == Direction.DOWN) {
return elevator.getCurrentFloor() - 1;
}
return elevator.getCurrentFloor();
}
private int getClosest(int a, int b) {
int x = Math.abs(a - elevator.getCurrentFloor());
int y = Math.abs(b - elevator.getCurrentFloor());
if (x <= y) {
return a;
} else {
return b;
}
}
private void openDoors() {
elevator.setState(State.STOPPED);
System.out.println("Open Door # Floor " + elevator.getCurrentFloor());
System.out.println("Close Door");
}
private void removeRequests(int currentFloor) {
// Remove internal requests
while (!queue.getInternalRequests().isEmpty() && queue.getInternalRequests().peek() == currentFloor) {
queue.getInternalRequests().removeFirst();
}
// Remove external requests
while (!queue.getExternalRequests().isEmpty() && queue.getExternalRequests().peek().getFloor() == currentFloor) {
ExternalRequest request = queue.getExternalRequests().peek();
if (request.getDirection() == elevator.getDirection()) {
queue.getExternalRequests().removeFirst();
} else if (queue.getInternalRequests().isEmpty() ||
(elevator.getDirection() == Direction.UP && queue.getInternalRequests().peek() < currentFloor) ||
(elevator.getDirection() == Direction.DOWN && queue.getInternalRequests().peek() > currentFloor)) {
queue.getExternalRequests().removeFirst();
} else {
break;
}
}
}
}
class Elevator {
private int minFloor, maxFloor, currentFloor;
private Direction direction;
private State state;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = minFloor;
this.direction = Direction.IDLE;
this.state = State.STOPPED;
}
public int getCurrentFloor() {
return currentFloor;
}
public void setCurrentFloor(int currentFloor) {
this.currentFloor = currentFloor;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public int getMinFloor() {
return minFloor;
}
public int getMaxFloor() {
return maxFloor;
}
public boolean isValidFloor(int floor) {
return floor >= minFloor && floor <= maxFloor;
}
}
class ExternalRequest {
private int floor;
private Direction direction;
public ExternalRequest(int floor, Direction direction) {
this.floor = floor;
this.direction = direction;
}
public int getFloor() {
return floor;
}
public Direction getDirection() {
return direction;
}
}
enum Direction {
UP,
DOWN,
IDLE
}
enum State {
MOVING,
STOPPED
}
类图:

类设计:
- (Elevator) 电梯类:
- 属性:包含最小楼层minFloor、最大楼层maxFloor、当前楼层currentFloor、运行方向direction(枚举类型Direction)和运行状态state(枚举类型State)。通过这些属性完整描述电梯的状态信息。
- 方法:提供获取和设置楼层、方向、状态的方法,以及判断楼层有效性的isValidFloor方法,确保电梯运行逻辑的完整性与数据合法性。
- (RequestQueue) 电梯请求队列类:
- 属性:分别使用LinkedList存储内部请求队列internalRequests和外部请求队列externalRequests,其中外部请求以ExternalRequest对象形式存储,包含目标楼层和方向信息。
- 方法:getQueueInstance方法负责解析用户输入并将请求加入对应队列,同时验证楼层有效性;addInternalRequest和addExternalRequest用于添加请求,增强了请求处理的模块化。
- (ExternalRequest) 外部请求类:
- 属性:包含目标楼层floor和请求方向direction(枚举类型Direction),清晰封装外部请求的核心信息。
- 作用:作为外部请求的载体,使请求队列能更直观地管理外部请求数据。
- (Controller) 控制类:
- 属性:持有Elevator和RequestQueue对象,作为电梯运行逻辑的核心协调者。
- 方法:
processRequests方法驱动整个电梯运行流程,包括方向判断、楼层移动、停靠判断和请求移除;
determineDirection方法根据内外请求情况调整电梯方向,相较于第一次题目集,逻辑更加清晰;
shouldStop方法综合考虑内外请求和电梯运行方向,判断是否需要停靠,优化了停靠策略。
- (Main) 主类:
负责初始化电梯楼层范围、创建Elevator、RequestQueue和Controller对象,并启动请求处理流程。相较于第一次题目集,将输入处理和核心逻辑分离,使Main类职责更单一,仅专注于对象初始化和流程启动。
点击查看SourceMontor的生成报表内容







分析与心得:
- 模块化与职责分离:第二次题目集在设计上明显优于第一次,将不同功能拆分到独立的类中,降低了类之间的耦合度,提升了代码的可维护性和扩展性。
- 逻辑优化:在determineDirection方法中,通过分层判断内外请求优先级和方向,简化了第一次题目集中复杂的嵌套逻辑,
- 不足之处:Controller类中的processRequests方法依然包含较多核心逻辑,如方向判断、移动、停靠等,可进一步拆分至更小的方法或独立类中,遵循单一职责原则。
- 心得:通过完成第二次题目集,我深刻体会到合理的类划分和职责分配,不仅使代码结构更清晰,也大幅降低了调试和维护的难度。同时,使用枚举类型和集合框架(如LinkedList)替代原始数据结构和自定义链表,显著提升了开发效率和代码稳定性。
第三次题目集
点击查看代码
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int minfloor = scanner.nextInt();
int maxfloor = scanner.nextInt();
Elevator elevator = new Elevator(minfloor, maxfloor);
RequestQueue requestQueue = new RequestQueue().getQueueInstance(scanner);
Controller controller = new Controller(elevator, requestQueue);
controller.processRequests();
scanner.close();
}
}
class Controller {
private Elevator elevator;
private RequestQueue queue;
public Controller() {
}
public Controller(Elevator elevator, RequestQueue queue) {
this.elevator = elevator;
this.queue = queue;
}
public Elevator getElevator() {
return elevator;
}
public void setElevator(Elevator elevator) {
this.elevator = elevator;
}
public RequestQueue getQueue() {
return queue;
}
public void setQueue(RequestQueue queue) {
this.queue = queue;
}
public void processRequests() {
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: UP");
while (!queue.getInternalRequests().isEmpty() || !queue.getExternalRequests().isEmpty()) {
determineDirection();
move();
System.out
.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
if (shouldStop(elevator.getCurrentFloor())) {
openDoors();
removeRequests(elevator.getCurrentFloor());
}
// 如果队列已空,提前终止
if (queue.getInternalRequests().isEmpty() && queue.getExternalRequests().isEmpty()) {
break;
}
}
elevator.setState(State.STOPPED);
}
private void determineDirection() {
if (elevator.getDirection() == Direction.IDLE) {
if (!queue.getExternalRequests().isEmpty()) {
elevator.setDirection(Direction.UP);
}
elevator.setState(State.MOVING);
return;
}
if (!queue.getInternalRequests().isEmpty()) {
int internalFirst = queue.getInternalRequests().peek().getDestinationFloor();
if (elevator.getDirection() == Direction.UP) {
if (internalFirst <= elevator.getCurrentFloor()) {
if (queue.getExternalRequests().isEmpty()) {
elevator.setDirection(Direction.DOWN);
} else {
int externalFirst = queue.getExternalRequests().peek().getSourceFloor();
if (externalFirst <= elevator.getCurrentFloor()) {
elevator.setDirection(Direction.DOWN);
}
}
}
} else if (elevator.getDirection() == Direction.DOWN) {
if (internalFirst >= elevator.getCurrentFloor()) {
if (queue.getExternalRequests().isEmpty()) {
elevator.setDirection(Direction.UP);
} else {
int externalFirst = queue.getExternalRequests().peek().getSourceFloor();
if (externalFirst >= elevator.getCurrentFloor()) {
elevator.setDirection(Direction.UP);
}
}
}
}
} else {
if (!queue.getExternalRequests().isEmpty()) {
int externalFirst = queue.getExternalRequests().peek().getSourceFloor();
if (elevator.getDirection() == Direction.UP && externalFirst <= elevator.getCurrentFloor()) {
elevator.setDirection(Direction.DOWN);
} else if (elevator.getDirection() == Direction.DOWN && externalFirst >= elevator.getCurrentFloor()) {
elevator.setDirection(Direction.UP);
}
}
}
}
private void move() {
elevator.setState(State.MOVING);
elevator.setCurrentFloor(getNextFloor());
}
private boolean shouldStop(int floor) {
// 检查内部请求
if (!queue.getInternalRequests().isEmpty()) {
Passenger internalReq = queue.getInternalRequests().peek();
if (internalReq != null && internalReq.getDestinationFloor() == floor) {
return true;
}
}
// 检查外部请求
if (!queue.getExternalRequests().isEmpty()) {
Passenger externalReq = queue.getExternalRequests().peek();
if (externalReq != null && externalReq.getSourceFloor() == floor) {
if (externalReq.getDirection() == elevator.getDirection()) {
return true;
}
if (queue.getInternalRequests().isEmpty()) {
return true;
}
Passenger internalReq = queue.getInternalRequests().peek();
if ((elevator.getDirection() == Direction.UP &&
internalReq.getDestinationFloor() < floor) ||
(elevator.getDirection() == Direction.DOWN &&
internalReq.getDestinationFloor() > floor)) {
return true;
}
}
}
return false;
}
private int getNextFloor() {
if (elevator.getDirection() == Direction.UP)
return elevator.getCurrentFloor() + 1;
else if (elevator.getDirection() == Direction.DOWN)
return elevator.getCurrentFloor() - 1;
return elevator.getCurrentFloor();
}
private int getClosest(int a, int b) {
int x = Math.abs(a - elevator.getCurrentFloor());
int y = Math.abs(b - elevator.getCurrentFloor());
if (x <= y) {
return a;
} else {
return b;
}
}
private void openDoors() {
elevator.setState(State.STOPPED);
System.out.println("Open Door # Floor " + elevator.getCurrentFloor());
System.out.println("Close Door");
}
private void removeRequests(int currentFloor) {
if (!queue.getInternalRequests().isEmpty()
&& queue.getInternalRequests().peek().getDestinationFloor() == currentFloor) {
queue.getInternalRequests().removeFirst();
return;
}
if (!queue.getExternalRequests().isEmpty()
&& queue.getExternalRequests().peek().getSourceFloor() == currentFloor) {
Passenger p = new Passenger(queue.getExternalRequests().peek().getDestinationFloor());
queue.addInternalRequest(p);
queue.getExternalRequests().removeFirst();
return;
}
}
}
class Passenger {
private Integer sourceFloor = null;//源楼层
private Integer destinationFloor = null;//目标层
public Passenger() {
}
public Passenger(Integer sourceFloor, Integer destinationFloor) {
this.sourceFloor = sourceFloor;
this.destinationFloor = destinationFloor;
}
public Passenger(Integer destinationFloor) {
this.destinationFloor = destinationFloor;
}
public Integer getSourceFloor() {
return sourceFloor;
}
public void setSourceFloor(Integer sourceFloor) {
this.sourceFloor = sourceFloor;
}
public Integer getDestinationFloor() {
return destinationFloor;
}
public void setDestinationFloor(Integer destinationFloor) {
this.destinationFloor = destinationFloor;
}
public Direction getDirection() {
if (sourceFloor != null && destinationFloor != null) {
if (sourceFloor > destinationFloor) {
return Direction.DOWN;
} else if (sourceFloor < destinationFloor) {
return Direction.UP;
}
}
return Direction.IDLE;
}
}
class RequestQueue {
private LinkedList<Passenger> internalRequests = new LinkedList<>();
private LinkedList<Passenger> externalRequests = new LinkedList<>();
public RequestQueue() {
}
public RequestQueue getQueueInstance(Scanner scanner) {
while (scanner.hasNextLine()) {
String request = scanner.nextLine().trim();
if (request.equalsIgnoreCase("end")) {
break;
}
if (!request.isEmpty()) {
if (request.matches("<\\d+>")) {
int destinationFloor = Integer.parseInt(request.substring(1, request.length() - 1));
Passenger passenger = new Passenger(destinationFloor);
this.addInternalRequest(passenger);
} else if (request.matches("<\\d+,\\d+>")) {
String[] parts = request.substring(1, request.length() - 1).split(",");
int currentFloor = Integer.parseInt(parts[0]);
int destinationFloor = Integer.parseInt(parts[1]);
Passenger passenger = new Passenger(currentFloor,destinationFloor);
this.addExternalRequest(passenger);
}
}
}
return this;
}
public LinkedList<Passenger> getInternalRequests() {
return internalRequests;
}
public void setInternalRequests(LinkedList<Passenger> internalRequests) {
this.internalRequests = internalRequests;
}
public LinkedList<Passenger> getExternalRequests() {
return externalRequests;
}
public void setExternalRequests(LinkedList<Passenger> externalRequests) {
this.externalRequests = externalRequests;
}
public void addInternalRequest(Passenger passenger) {
if (!internalRequests.contains(passenger.getDestinationFloor())) {
internalRequests.add(passenger);
}
}
public void addExternalRequest(Passenger passenger) {
externalRequests.add(passenger);
}
}
class Elevator {
private int minFloor, maxFloor, currentFloor;
private Direction direction;
private State state;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = minFloor;
this.direction = Direction.IDLE;
this.state = State.STOPPED;
}
public int getCurrentFloor() {
return currentFloor;
}
public void setCurrentFloor(int currentFloor) {
if (currentFloor >= minFloor && currentFloor <= maxFloor) {
this.currentFloor = currentFloor;
}
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public int getMinFloor() {
return minFloor;
}
public int getMaxFloor() {
return maxFloor;
}
public boolean isValidFloor(int floor) {
return floor >= minFloor && floor <= maxFloor;
}
}
enum Direction{
UP,
DOWN,
IDLE
}
enum State{
MOVING,
STOPPED
}
类图

类设计
- (Elevator) 电梯类
- 属性:与第二次题目集类似,包含最小楼层minFloor、最大楼层maxFloor、当前楼层currentFloor、运行方向direction(枚举类型Direction)和运行状态state(枚举类型State) 。新增了对currentFloor设置时的楼层范围校验,保证电梯楼层数据始终处于合法区间。
- 方法:除了基本的获取和设置属性方法,以及判断楼层有效性的isValidFloor方法外,在setCurrentFloor方法中加入了合法性判断逻辑,增强了数据的准确性和程序的健壮性。
- (RequestQueue) 电梯请求队列类
- 属性:使用LinkedList分别存储内部请求队列internalRequests和外部请求队列externalRequests,队列元素类型为Passenger,Passenger类封装了乘客的源楼层和目标楼层信息,相比第二次题目集,能更全面地描述请求内容。
- 方法:getQueueInstance方法用于解析用户输入并将请求加入对应队列,同时进行输入格式校验;addInternalRequest方法增加了对重复目标楼层请求的过滤逻辑,避免无效请求堆积;addExternalRequest方法则负责添加外部乘客请求。
- (Passenger) 乘客类
- 属性:包含源楼层sourceFloor和目标楼层destinationFloor,用于记录乘客的起始和目标位置。通过getDirection方法可根据源楼层和目标楼层自动计算出行方向,方便电梯调度逻辑判断。
- 作用:作为请求队列的基本元素,将乘客请求信息进行封装,使请求处理逻辑更具语义化和可扩展性。
- (Controller) 控制类
- 属性:持有Elevator和RequestQueue对象,作为协调电梯运行和请求处理的核心类。
- 方法:
processRequests方法驱动电梯运行主流程,包括方向判断、楼层移动、停靠判断和请求移除,同时新增了在请求队列为空时提前终止循环的逻辑,提高了程序运行效率。
determineDirection方法在判断电梯运行方向时,基于乘客的源楼层和目标楼层信息,综合考虑内外请求情况,逻辑更加严谨。
shouldStop方法用于判断电梯是否应在当前楼层停靠,综合了内外请求、电梯运行方向以及内部请求的目标楼层等多个因素,确保停靠决策的合理性。
removeRequests方法在处理请求移除时,将外部请求乘客转换为内部请求乘客,更好地模拟了实际电梯运行场景中的乘客运输过程。
- (Main) 主类:负责初始化电梯楼层范围,创建Elevator、RequestQueue和Controller对象,并启动请求处理流程。相较于前两次题目集,代码结构更加简洁明了,专注于程序的初始化和启动,进一步遵循了职责分离原则。
分析与心得:
- 第三次题目集在功能上相比第二次有了显著扩展,引入Passenger类更细致地描述请求信息,提升了程序的实用性。
- 不足:Controller类的部分方法(如processRequests)逻辑依然较为复杂,代码行数较多,可进一步拆分细化,提高代码的可读性和可维护性。代码中缺乏对异常情况的全面处理,例如当输入数据格式严重错误时,程序可能出现运行时异常,未进行有效的捕获和处理。
三、 采坑心得
第一次看到这个题目,觉得字好多而且占70%的分数一定很困难,尝试把题目通读了一遍,果不其然,没理解什么意思。看了排名,整个年级没人写出来,就想着先放一放。后面尝试理解题目大意后,考虑到有很多增删操作,决定使用链表,但由于不知道有LinkedList库函数可以直接使用,于是设计一个链表类,便有了如下的代码
点击查看代码
import java.util.Scanner;
class RequestNode {
int floor;
int direction; // 1:UP, -1:DOWN, 0:内部请求
RequestNode next;
public RequestNode(int floor, int direction) {
this.floor = floor;
this.direction = direction;
this.next = null;
}
}
class Elevator {
private final int maxFloor;
private final int minFloor;
private int curFloor;
private int direction; // 1:UP, 0:IDLE, -1:DOWN
private int state; // 0:STOPPED, 1:MOVING
private RequestNode internalRequests; // 内部请求链表
private RequestNode externalRequests; // 外部请求链表
//构造函数
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.curFloor = minFloor;
this.direction = 0;
this.state = 0;
this.internalRequests = null;
this.externalRequests = null;
}
// 添加请求到对应链表
public void addRequest(String request) {
if (request.matches("<\\d+>")) { // 内部请求
int floor = Integer.parseInt(request.substring(1, request.length()-1));
if(validateFloor(floor)) {
internalRequests = appendToList(internalRequests, new RequestNode(floor, 0));
activateElevator();
}
}
else if (request.matches("<\\d,UP>")) { // 外部上行请求
int floor = Integer.parseInt(request.substring(1, request.indexOf(',')));
if(validateFloor(floor)) {
externalRequests = appendToList(externalRequests, new RequestNode(floor, 1));
activateElevator();
}
}
else if (request.matches("<\\d+,DOWN>")) { // 外部下行请求
int floor = Integer.parseInt(request.substring(1, request.indexOf(',')));
if(validateFloor(floor)) {
externalRequests = appendToList(externalRequests, new RequestNode(floor, -1));
activateElevator();
}
}
}
// 处理所有请求
public void processRequests() {
System.out.println("Current Floor: 1 Direction: UP");
while (hasPendingRequests()) {
// 检查当前楼层是否需要停靠
if (shouldStop(curFloor)) {
System.out.println("Open Door # Floor " + curFloor);
removeRequestsAtCurrentFloor();
System.out.println("Close Door");
}
if(hasPendingRequests()) {
// 移动电梯
moveOneFloor();
}
// 检查是否需要改变方向
checkDirectionChange();
}
// 无请求时回到空闲状态
direction = 0;
state = 0;
}
// 验证楼层有效性
private boolean validateFloor(int floor) {
return floor >= minFloor && floor <= maxFloor;
}
// 激活电梯(当有新的请求时)
private void activateElevator() {
if (state == 0 && direction == 0) {
determineInitialDirection();
}
}
// 确定初始方向
private void determineInitialDirection() {
if (hasRequestAbove(internalRequests,curFloor)||hasRequestAbove(externalRequests,curFloor)) {
direction = 1;
} else if (hasRequestBelow(internalRequests,curFloor)||hasRequestBelow(externalRequests,curFloor)) {
direction = -1;
}
state = 1;
}
// 检查上方是否有请求
private boolean hasRequestAbove(RequestNode head, int floor) {
if (head == null) {
return false;
}
RequestNode current = head;
if (current.floor > floor) return true;
return false;
}
//检查下方是否有请求
private boolean hasRequestBelow(RequestNode head, int floor) {
if (head == null) {
return false;
}
RequestNode current = head;
if (current.floor < floor) return true;
return false;
}
// 向链表末尾添加节点
private RequestNode appendToList(RequestNode head, RequestNode newNode) {
if (head == null) {
return newNode;
}
RequestNode current = head;
while (current.next != null) {
current = current.next;
}
current.next = newNode;
return head;
}
// 判断是否有待处理请求
private boolean hasPendingRequests() {
return internalRequests != null || externalRequests != null;
}
// 判断是否应在当前楼层停靠
private boolean shouldStop(int floor) {
// 检查内部请求
if (containsFloor(internalRequests, floor)) {
return true;
}
// 检查同方向的外部请求
RequestNode current = externalRequests;
if (containsFloor(externalRequests, floor)) {
if (direction == 0 || current.direction == direction) {
return true;
}
}
return false;
}
// 从链表中移除当前楼层所有请求
private void removeRequestsAtCurrentFloor() {
internalRequests = removeFromList(internalRequests, curFloor);
externalRequests = removeFromList(externalRequests, curFloor);
}
// 从链表中删除指定楼层的所有节点
private RequestNode removeFromList(RequestNode head, int floor) {
RequestNode dummy = new RequestNode(0, 0);
dummy.next = head;
RequestNode prev = dummy;
RequestNode current = head;
if(current==null) {
return null;
}
if (current.floor == floor) {
prev.next = current.next;
}
return dummy.next;
}
// 移动一层
private void moveOneFloor() {
if (direction == 1 && curFloor < maxFloor) {
curFloor++;
} else if (direction == -1 && curFloor > minFloor) {
curFloor--;
}
state = 1;
System.out.println("Current Floor: " + curFloor + " Direction: " + getDirectionString());
}
// 获取方向字符串
private String getDirectionString() {
switch (direction) {
case 1: return "UP";
case -1: return "DOWN";
default: return "IDLE";
}
}
// 检查是否需要改变方向
private void checkDirectionChange() {
if (direction == 1 && !hasRequestAbove(internalRequests,curFloor)&&!hasRequestAbove(externalRequests,curFloor)) {
direction = -1;
} else if (direction == -1 && !hasRequestBelow(internalRequests,curFloor)&&!hasRequestBelow(externalRequests,curFloor)) {
direction = 1;
}
}
// 检查链表中第一个是否为指定楼层
private boolean containsFloor(RequestNode head, int floor) {
if(head==null) {
return false;
}
if (head.floor == floor) {
return true;
}
return false;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取楼层范围
int minFloor = sc.nextInt();
int maxFloor = sc.nextInt();
Elevator elevator = new Elevator(minFloor, maxFloor);
// 处理请求输入
while (sc.hasNextLine()) {
String input = sc.nextLine().trim();
if (input.equalsIgnoreCase("end")) {
break;
}
elevator.addRequest(input);
}
elevator.processRequests();
}
}
后面根据老师给的提示选择使用LinkedList库函数,但是不懂得一个节点怎么同时储存楼层数和方向,跟其他已经完成的同学交流,得知她使用了三个链表,便尝试自己写
于是有了如下代码
点击查看代码
import java.util.Scanner;
import java.util.LinkedList;
import java.util.Queue;
class Elevator {
private final int maxFloor;
private final int minFloor;
private int currentFloor;
private int direction; // 1:UP, 0:IDLE, -1:DOWN
private int state; // 0:STOPPED, 1:MOVING
private Queue<Integer> internalRequests;// 内部请求链表
private Queue<Integer> externalRequests;// 外部请求链表
private Queue<Integer> externalRequestsDir;// 外部请求链表对应方向
//构造函数
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = minFloor;
this.direction = 0;
this.state = 0;
this.internalRequests = new LinkedList<>();
this.externalRequests = new LinkedList<>();
this.externalRequestsDir = new LinkedList<>();
}
// 添加请求到对应链表
public void addRequest(String request) {
if (request.matches("<\\d+>")) { // 内部请求
int floor = Integer.parseInt(request.substring(1, request.length()-1));
if(validateFloor(floor)) {
internalRequests.add(floor);
}
}
else if (request.matches("<\\d,UP>")) { // 外部上行请求
int floor = Integer.parseInt(request.substring(1, request.indexOf(',')));
if(validateFloor(floor)) {
externalRequests.add(floor);
externalRequestsDir.add(1);
}
}
else if (request.matches("<\\d+,DOWN>")) { // 外部下行请求
int floor = Integer.parseInt(request.substring(1, request.indexOf(',')));
if(validateFloor(floor)) {
externalRequests.add(floor);
externalRequestsDir.add(-1);
}
}
}
public void processRequests() {
System.out.println("Current Floor: 1 Direction: UP");
while (hasPendingRequests()) {
checkDirectionChange();
if (shouldStop(currentFloor)) {
System.out.println("Open Door # Floor " + currentFloor);
removeRequestsAtCurrentFloor();
System.out.println("Close Door");
}
if (hasPendingRequests()) {
moveOneFloor();
}
}
direction = 0;
state = 0;
}
private boolean validateFloor(int floor) {
if (floor < minFloor || floor > maxFloor) {
return false;
}
return true;
}
void activateElevator() {
if (state == 0 && direction == 0) {
determineInitialDirection();
state = 1;
}
}
private void determineInitialDirection() {
if (hasRequestAbove(currentFloor)) {
direction = 1;
} else if (hasRequestBelow(currentFloor)) {
direction = -1;
}
}
private boolean hasRequestAbove(int floor) {
return hasHigherRequest(internalRequests, floor) ||
hasHigherRequest(externalRequests, floor);
}
private boolean hasRequestBelow(int floor) {
return hasLowerRequest(internalRequests, floor) ||
hasLowerRequest(externalRequests, floor) ;
}
// 检查上方是否有请求
private boolean hasHigherRequest(Queue<Integer> queue, int floor) {
return !queue.isEmpty() && queue.peek() > floor;
}
private boolean hasLowerRequest(Queue<Integer> queue, int floor) {
return !queue.isEmpty() && queue.peek() < floor;
}
private boolean hasPendingRequests() {
return !internalRequests.isEmpty() ||
!externalRequests.isEmpty() ;
}
private boolean shouldStop(int floor) {
// 检查内部请求
if (!internalRequests.isEmpty() && internalRequests.peek() == floor) {
return true;
}
// 检查外部请求
if (!externalRequests.isEmpty() && externalRequests.peek() == floor && externalRequestsDir.peek() == direction) {
return true;
}
return false;
}
private void removeRequestsAtCurrentFloor() {
// 移除内部请求
if (!internalRequests.isEmpty() && internalRequests.peek() == currentFloor) {
internalRequests.poll();
}
// 移除外部请求
if (!externalRequests.isEmpty() && externalRequests.peek() == currentFloor && externalRequestsDir.peek() == direction) {
externalRequests.poll();
externalRequestsDir.poll();
}
}
private void moveOneFloor() {
if (direction == 1 && currentFloor < maxFloor) {
currentFloor++;
} else if (direction == -1 && currentFloor > minFloor) {
currentFloor--;
}
System.out.println("Current Floor: " + currentFloor + " Direction: " + getDirectionString());
}
private String getDirectionString() {
switch (direction) {
case 1: return "UP";
case -1: return "DOWN";
default: return "IDLE";
}
}
private void checkDirectionChange() {
if ((hasHigherRequest(externalRequests,currentFloor)&&externalRequestsDir.peek() == 1) && !hasLowerRequest(internalRequests,currentFloor)) {
direction = 1;
} else if ((hasLowerRequest(externalRequests,currentFloor)&&externalRequestsDir.peek() == -1) && !hasHigherRequest(internalRequests,currentFloor)) {
direction = -1;
}
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取楼层范围
int minFloor = sc.nextInt();
int maxFloor = sc.nextInt();
Elevator elevator = new Elevator(minFloor, maxFloor);
// 处理请求输入
while (sc.hasNextLine()) {
String input = sc.nextLine().trim();
if (input.equalsIgnoreCase("end")) {
break;
}
elevator.addRequest(input);
}
elevator.processRequests();
}
}
第二次题目并没有做逻辑上的修改,而是根据题目所给类图来进行类设计,理清楚每个类有哪些方法,每个方法干什么。在第一次题目理解的基础上,第二次相对来说就比较容易了
第三次修改了部分逻辑,外部请求不再是输入楼层数和方向,而是改为源楼层和目标楼层。我根据题目修改了部分类设计和逻辑,没有改变主体逻辑,但是没有通过后面两个测试点只拿了一般的分数。在截止前,我尝试各种边界值的测试,跟同学们交流,他们中很多人都是不大块修改就可以通过,我也尝试多次,但最终还是没能成功。
四、改进建议
减少不必要的队列操作:在处理请求队列时,避免频繁地调用peek和remove方法。以第三次题目集为例,在determineDirection和shouldStop方法中,对请求队列的操作可以先将相关请求信息提取到临时变量中,减少对队列的多次访问。如将queue.getInternalRequests().peek().getDestinationFloor()的值先赋给一个临时变量nextInternalFloor,后续使用该变量进行逻辑判断,提高代码执行效率。
优化循环逻辑:在主循环处理请求的代码中,如Controller类的processRequests方法的循环,减少循环内部不必要的计算和判断。可以在循环开始前先判断请求队列是否为空,如果为空则直接结束循环,避免进入循环后再进行多次条件判断,降低时间复杂度。
五、总结
通过完成这三次 Java 大作业题目集,我在多个方面实现了显著成长。在技术层面,从最初对题目理解的迷茫,到逐步掌握面向对象编程的核心思想,学会合理设计类和封装方法,能够根据需求不断优化代码结构与逻辑。同时,对 Java 语法的运用更加熟练,尤其是集合框架的使用,极大提升了开发效率。
在解决问题的能力上,每次作业都如同一次挑战,从最初因代码运行超时、逻辑错误而不知所措,到后来通过分析复杂度、调试代码、与同学交流等方式逐步攻克难题,学会了如何从复杂问题中抽丝剥茧,找到问题的本质并加以解决。
然而,也暴露出许多不足。在代码设计上,对设计模式的运用不够熟练,导致部分代码结构不够清晰,耦合度较高;在性能优化方面,对时间和空间复杂度的分析不够深入,未能在开发初期就做出更优的算法和数据结构选择;在错误处理上,缺乏全面的考虑,使程序在面对异常情况时不够健壮。
未来,我将深入学习设计模式,提升代码的架构设计能力;加强对算法和数据结构的学习,提高在复杂场景下选择最优解决方案的能力;养成良好的编程习惯,注重代码的规范、注释和异常处理,确保程序的稳定性和可维护性。这些经历不仅是一次学习的过程,更为我今后的编程之路奠定了坚实的基础,让我有信心面对更大的挑战。

浙公网安备 33010602011771号