Java简易票务模拟器非顺序出票报错问题排查
问题背景
正在开发简易票务模拟程序:
- 定义
Seats类,使用静态LinkedList存储放映厅全部座位 - 共50个座位,每10个为一排,对应排号a到e,1-10为a排、11-20为b排,以此类推
- 出票逻辑为:用户输入排号+座位号,匹配到对应可用座位后从列表中移除,避免重复预订
- 测试时发现仅按a1、a2、a3……的顺序出票能正常运行,非顺序出票(例如买完a1-a4后买b11)会误判座位已被出票,怀疑LinkedList要求必须按顺序操作。
原代码如下:Seats类:
public class Seats { public static LinkedList<Seats> seatsInSaloon; private final int seatNumber; private final char seatChar; public Seats(int seatNumber, char seatChar) { this.seatChar = seatChar; this.seatNumber = seatNumber; } private static void generateSeats() { seatsInSaloon = new LinkedList<Seats>(); char x = 'a'; for (int i = 1; i < 51; i++) { if (i % 10 == 0) { Seats seats = new Seats(i, x); seatsInSaloon.add(seats); x++; } else { Seats seats = new Seats(i, x); seatsInSaloon.add(seats); } } } public int getSeatNumber() { return seatNumber; } public char getSeatChar() { return seatChar; } public static void fillSeats() { generateSeats(); } }
Ticketing类:
public class Ticketing { private static Seats seats; public static LinkedList<Seats> seeAllSeatsAvailable() { return Seats.seatsInSaloon; } public static void ticketSeat(int seatNum, char seatChar) { if ((seatNum > 50 || seatNum < 1) || (seatChar > 'e' || seatChar < 'a')) { System.out.println("please check the numbers you have entered .... "); } for (Seats s : Seats.seatsInSaloon) { if (s.getSeatChar() == seatChar && s.getSeatNumber() == seatNum) { System.out.println("HERE IS YOUR TICKET : " + seatChar + seatNum); Seats.seatsInSaloon.remove(s); break; } else if (!Seats.seatsInSaloon.contains(s.getSeatChar() == seatChar && s.getSeatNumber() == seatNum)) { System.out.println("sorry... This ticket has already been issued"); break; } } } }
测试代码:
public class TicketDriver { public static void main(String[] args) { Seats.fillSeats(); Ticketing.ticketSeat(1, 'a'); //正常 Ticketing.ticketSeat(2, 'a'); //正常 Ticketing.ticketSeat(3, 'a'); //正常 Ticketing.ticketSeat(4, 'a'); //正常 Ticketing.ticketSeat(4, 'a'); //正常,提示已出票 Ticketing.ticketSeat(11, 'b'); //误报已出票 } }
问题原因
这个问题和LinkedList数据结构本身无关,完全是ticketSeat方法的逻辑错误导致的,共有3处核心问题:
- 遍历判断逻辑完全错误:for循环逐个遍历列表元素时,只要第一个元素不匹配目标座位,就会进入
else if分支,直接打印错误提示并break终止遍历,根本不会访问列表后续的元素。顺序买a1-a4时,这几个座位刚好在列表最前端,第一个元素就能匹配成功,所以不会触发问题;买b11时,列表第一个元素是a5,和目标不匹配,直接就走错误分支了。 contains方法使用错误:List.contains()方法的参数是要查找的列表元素,传入的布尔表达式(运算结果是true/false)和列表存储的Seats类型完全不匹配,因此这个判断永远返回false,取反后永远为true,只要第一个元素不匹配就必然触发错误提示。- 参数校验缺少返回逻辑:判断输入参数非法后,没有执行
return终止方法,就算输入不符合要求,代码还是会继续往下执行遍历逻辑。
另外Seats类的generateSeats方法中if和else分支的添加座位逻辑完全重复,属于冗余代码,不影响功能但可以简化。
修复方案
调整ticketSeat方法的执行逻辑:
- 参数校验不通过时直接返回,不执行后续逻辑
- 遍历整个可用座位列表查找匹配项,找到后打印出票信息、移除座位,直接终止方法
- 完整遍历完列表都没找到匹配座位时,才提示座位已被出票
修正后的代码如下:
public static void ticketSeat(int seatNum, char seatChar) { // 参数非法直接终止方法 if ((seatNum > 50 || seatNum < 1) || (seatChar > 'e' || seatChar < 'a')) { System.out.println("please check the numbers you have entered .... "); return; } // 遍历所有可用座位查找匹配项 for (Seats s : Seats.seatsInSaloon) { if (s.getSeatChar() == seatChar && s.getSeatNumber() == seatNum) { System.out.println("HERE IS YOUR TICKET : " + seatChar + seatNum); Seats.seatsInSaloon.remove(s); return; } } // 遍历完未找到匹配项,说明座位已出票 System.out.println("sorry... This ticket has already been issued"); }
注:for-each遍历过程中直接调用List的remove方法会触发并发修改异常,当前代码因为移除元素后直接return不会继续迭代,所以暂时不会触发问题,如果后续需要扩展逻辑,建议使用Iterator的remove方法执行删除操作。
内容的提问来源于stack exchange,提问作者user10525734
相关产品推荐
相关产品推荐

