船舱订票系统测试

package com.dong.mytest.demo.other.yan;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class TicketSystem {

    /**
     * 订单状态 0-初始状态 1-预定失败 2-预定成功 3-已取消
     */
    public static final Integer ORDER_STATUS_INIT = 0;
    public static final Integer ORDER_STATUS_FAILED = 1;
    public static final Integer ORDER_STATUS_SUCCESS = 2;
    public static final Integer ORDER_STATUS_CANCEL = 3;

    /**
     * 座位状态 0-空位 1-已预订
     */
    public static final Integer SEAT_STATUS_EMPTY = 0;
    public static final Integer SEAT_STATUS_ORDERED = 1;

    /**
     * 舱位id map
     */
    private Map<Integer, Cabin> cabinMap = new HashMap<>(16);

    /**
     * 订单map
     */
    private Map<Integer, TicketOrder> orderMap = new HashMap<>(16);

    public TicketSystem(int[] cabins) {
        if (cabins == null) {
            throw new RuntimeException("初始化参数错误");
        }
        // 初始化每个船舱的信息:id,座位列表,候补队列
        for (int i = 0; i < cabins.length; i++) {
            int cabinCount = cabins[i];
            List<Integer> seatList = new ArrayList<>(cabinCount);
            for (int j = 0; j < cabinCount; j++) {
                // 0-空位 1-已被定
                seatList.add(SEAT_STATUS_EMPTY);
            }
            Cabin cabin = new Cabin();
            cabin.setCabinId(i);
            cabin.setSeatList(seatList);
            cabinMap.put(i, cabin);
        }
    }

    /**
     * 从cabinId舱位中预定num个座位,订单编号为id
     */
    public boolean book(int id, int cabinId, int num) {
        if (cabinMap.get(cabinId) == null) {
            System.out.println("cabinId有误");
            return false;
        }
        if (orderMap.containsKey(id)) {
            System.out.println("订单id已存在,请确认后再试");
            return false;
        }
        Cabin cabin = cabinMap.get(cabinId);
        // 生成订单
        TicketOrder order = new TicketOrder();
        order.setId(id);
        order.setCabinId(cabinId);
        order.setNum(num);
        order.setStatus(ORDER_STATUS_INIT);
        orderMap.put(id, order);
        // 该船舱的候补队列
        List<TicketOrder> hbQueue = cabin.getHbQueue();
        // 候补队列为空
        if (hbQueue.isEmpty()) {
            // 该船舱剩余座位列表
            List<Integer> remainSeatNumList = cabin.getRemainSeatNumList();
            // 有足够余票
            if (remainSeatNumList.size() >= num) {
                // 根据连续优先订票规则,获取座位号
                List<Integer> seatNumList = checkHasContinuousSeatNum(remainSeatNumList, num);
                for (Integer seatNum : seatNumList) {
                    // 修改座位号状态
                    cabin.getSeatList().set(seatNum, SEAT_STATUS_ORDERED);
                }
                // 记录订单预定的座位列表
                order.setOrderSeatNumList(seatNumList);
                order.setStatus(ORDER_STATUS_SUCCESS);
                return true;
            } else {
                // 余票不足,该订单进入该船舱的候补队列队尾
                order.setStatus(ORDER_STATUS_FAILED);
                hbQueue.add(order);
                return false;
            }
        } else {
            // 候补队列非空,直接进入候补队列队尾
            order.setStatus(ORDER_STATUS_FAILED);
            hbQueue.add(order);
            return false;
        }
    }

    /**
     * 根据连续优先订票规则,获取座位号
     */
    private List<Integer> checkHasContinuousSeatNum(List<Integer> remainSeatNumList, int orderSeatCount) {
        // 连续座位号列表
        List<Integer> list = new ArrayList<>();
        // 上一个座位号
        Integer preSeatNum = null;
        for (Integer seatNum : remainSeatNumList) {
            // 如果当前座位号和上一个不是差1,则说明不连续,清空
            if (preSeatNum != null && !seatNum.equals(preSeatNum + 1)) {
                list.clear();
            }
            list.add(seatNum);
            // 如果连续座位号达到订票数,则直接返回
            if (list.size() >= orderSeatCount) {
                return list;
            }
            preSeatNum = seatNum;
        }
        // 走到这里说明没有连续的号,返回最小的几个座位号
        list.clear();
        for (Integer seatNum : remainSeatNumList) {
            if (list.size() < orderSeatCount) {
                list.add(seatNum);
            } else {
                break;
            }
        }
        return list;
    }

    /**
     * 取消编号为id的订单,并及时处理候补队列订单
     */
    public boolean cancel(int id) {
        if (orderMap.get(id) == null) {
            System.out.println("订单id不存在");
            return false;
        }
        TicketOrder order = orderMap.get(id);
        Cabin cabin = cabinMap.get(order.getCabinId());
        boolean result = false;
        // 如果该订单已预定成功,则成功取消订单、退票并返回true
        if (ORDER_STATUS_SUCCESS.equals(order.getStatus())) {
            // 回补座位
            List<Integer> orderSeatNumList = order.getOrderSeatNumList();
            for (Integer seatNum : orderSeatNumList) {
                // 将船舱的座位状态修改为 0-空位
                cabin.getSeatList().set(seatNum, SEAT_STATUS_EMPTY);
            }
            // 候补队列尝试继续买票
            queueRetry(cabin);
            result = true;
        } else if (ORDER_STATUS_FAILED.equals(order.getStatus())) {
            cabin.getHbQueue().removeIf(item -> item.getId() == order.getId());
            // 后面的候补队列尝试继续买票
            queueRetry(cabin);
            result = true;
        } else {
            // 其他:0-初始状态 3-已取消 直接返回false
        }
        // 修改订单状态
        order.setStatus(ORDER_STATUS_CANCEL);
        order.setOrderSeatNumList(new ArrayList<>());
        return result;
    }

    /**
     * 候补队列尝试继续买票
     */
    private void queueRetry(Cabin cabin) {
        Iterator<TicketOrder> iterator = cabin.getHbQueue().iterator();
        while (iterator.hasNext()) {
            TicketOrder ticketOrder = iterator.next();
            // 该船舱剩余座位列表
            List<Integer> remainSeatNumList = cabin.getRemainSeatNumList();
            // 没有足够的余票,直接退出
            if (remainSeatNumList.size() < ticketOrder.getNum()) {
                break;
            }
            // 有足够余票,根据连续优先订票规则,获取座位号
            List<Integer> seatNumList = checkHasContinuousSeatNum(remainSeatNumList, ticketOrder.getNum());
            for (Integer seatNum : seatNumList) {
                // 修改座位号状态
                cabin.getSeatList().set(seatNum, SEAT_STATUS_ORDERED);
            }
            // 记录订单预定的座位列表
            ticketOrder.setOrderSeatNumList(seatNumList);
            ticketOrder.setStatus(ORDER_STATUS_SUCCESS);
            // 从队列中移除
            iterator.remove();
        }
    }


    public int query(int id) {
        TicketOrder order = orderMap.get(id);
        if (order == null || !ORDER_STATUS_SUCCESS.equals(order.getStatus())) {
            return -1;
        }
        // 如果预定成功,则返回最小的座位号
        return order.getOrderSeatNumList().get(0);
    }

    public static void main(String[] args) {
        TicketSystem ticketSystem = new TicketSystem(new int[]{10, 1});
        System.out.println(ticketSystem.book(71, 0, 2));
        System.out.println(ticketSystem.book(73, 0, 10));
        System.out.println(ticketSystem.book(72, 0, 2));
        System.out.println(ticketSystem.query(72));
        System.out.println(ticketSystem.book(74, 0, 2));
        System.out.println(ticketSystem.cancel(73));
        System.out.println(ticketSystem.query(74));
        System.out.println(ticketSystem.query(72));
        System.out.println(ticketSystem.cancel(72));
        System.out.println(ticketSystem.book(75, 0, 3));
        System.out.println(ticketSystem.query(75));
        System.out.println(ticketSystem.cancel(75));
        System.out.println(ticketSystem.book(76, 0, 2));
        System.out.println(ticketSystem.book(77, 0, 2));
        System.out.println(ticketSystem.cancel(76));
        System.out.println(ticketSystem.book(78, 0, 3));
        System.out.println(ticketSystem.query(78));
    }
}
package com.dong.mytest.demo.other.yan;

import java.util.ArrayList;
import java.util.List;

public class Cabin {

    /**
     * 船舱编号
     */
    private int cabinId;

    /**
     * 座位列表,list下标代表座位号,0代表空位,1代表被定了
     */
    private List<Integer> seatList;

    /**
     * 候补队列
     */
    private List<TicketOrder> hbQueue = new ArrayList<>();

    /**
     * 获取剩余的座位号列表
     *
     * @return list
     */
    public List<Integer> getRemainSeatNumList() {
        List<Integer> remainSeatNumList = new ArrayList<>();
        for (int i = 0; i < seatList.size(); i++) {
            Integer flag = seatList.get(i);
            if (flag.equals(0)) {
                remainSeatNumList.add(i);
            }
        }
        return remainSeatNumList;
    }

    public int getCabinId() {
        return cabinId;
    }

    public void setCabinId(int cabinId) {
        this.cabinId = cabinId;
    }

    public List<Integer> getSeatList() {
        return seatList;
    }

    public void setSeatList(List<Integer> seatList) {
        this.seatList = seatList;
    }

    public List<TicketOrder> getHbQueue() {
        return hbQueue;
    }

    public void setHbQueue(List<TicketOrder> hbQueue) {
        this.hbQueue = hbQueue;
    }
}
package com.dong.mytest.demo.other.yan;

import java.util.List;

public class TicketOrder {

    /**
     * 订单id
     */
    private int id;

    /**
     * 预订的船舱id
     */
    private int cabinId;

    /**
     * 预定座位数
     */
    private int num;

    /**
     * 预定的座位编号列表
     */
    private List<Integer> orderSeatNumList;

    /**
     * 订单状态 0-初始状态 1-预定失败 2-预定成功 3-已取消
     */
    private int status;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public List<Integer> getOrderSeatNumList() {
        return orderSeatNumList;
    }

    public void setOrderSeatNumList(List<Integer> orderSeatNumList) {
        this.orderSeatNumList = orderSeatNumList;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public int getCabinId() {
        return cabinId;
    }

    public void setCabinId(int cabinId) {
        this.cabinId = cabinId;
    }

}
原文地址:https://www.cnblogs.com/dong320/p/15791085.html