【问题标题】:Creating an order-slot system with 2 array lists创建具有 2 个数组列表的订单槽系统
【发布时间】:2021-03-22 01:06:31
【问题描述】:

我需要编写一个 daymanagerr,为餐厅的订单分配时间段。

那是日常经理:

public DayManager (LocalDate date, int numberOfTimeSlots, int capacityPerSlot) {
        this.date = date;
        this.capacityPerSlot = capacityPerSlot;
        this.numberOfTimeSlots = numberOfTimeSlots;

对于每一天,我可以选择可用插槽的数量和每个插槽的容量(因此,如果我选择 3 个插槽并且每个插槽的容量为 3,则总共有 9 个插槽)。

每个客户都可以在订单中说明他们喜欢的时间段(此处:0、1 或 2)。

这是我添加订单的类:

public Optional<Integer> addOrder(Order order, int preferredSlot) {
            int givenSlot = 0, count = 1;
            List<Integer> slots = new ArrayList<Integer>();
            List<Integer> slotsPerSlot = new ArrayList<Integer>();

                if ((slots.size() * slotsPerSlot.size()) <= (numberOfTimeSlots * capacityPerSlot)) {
                    if (slots.contains(preferredSlot) == false) {
                        givenSlot = preferredSlot;
                        slots.add(preferredSlot);
                        slotsPerSlot.add(count);
                        count++;
                    } else if (slotsPerSlot.size() <= capacityPerSlot) {
                        givenSlot = preferredSlot;
                        slots.add(preferredSlot);
                        slotsPerSlot.add(slotsPerSlot.size() + 1);

                    } else {
                        givenSlot = slots.get(slots.lastIndexOf(count));
                    }
                    return Optional.of(givenSlot);
                }
                return Optional.empty();
            }
            
    

我需要什么帮助:

对于我收到的每一个新订单,我都需要检查该客户首选插槽中是否还有剩余容量。如果还有剩余容量,我会将那个位置分配给他。如果该插槽中没有剩余容量,我将分配具有下一个最低索引(和可用容量)的插槽。如果那天没有剩余容量,我就什么都不退。

我只是不知道如何为每个插槽创建一个 slotPerSlot 列表,另外我真的不知道如何获得下一个最低的插槽号。

【问题讨论】:

    标签: java


    【解决方案1】:

    多地图

    您可以使用multimapMap 是一对导致值的键。在 multimap 中,值实际上是值的集合,而不是单个值。

    例如,想象一个包含三个时隙的层次结构,其中第一个和最后一个包含一个空列表(还没有订单),而中间的时隙有一个单一订单的列表。

    • 2022-01-23T13:00-07:00[美国/埃德蒙顿]
      • []
    • 2022-01-23T14:00-07:00[美国/埃德蒙顿]
      • [订单[id=2d8e5cc2-26ac-474d-a081-2c71207fd6c5, customerName=Basil]]
    • 2022-01-23T15:00-07:00[美国/埃德蒙顿]
      • []

    (次要细节:2d8e5cc2-26ac-474d-a081-2c71207fd6c5 文本是一个 hexadecimal 字符串表示形式,用于标识该特定订单的 128 位 UUID 值。)

    示例代码

    这是一些示例代码。这段代码不完整,但会让你朝着正确的方向前进。

    首先,定义我们的Order 类。我们将使用 Java 16 中的新功能将其设为record。您也可以定义一个常规类,但记录要简单得多。编译器隐式创建构造函数、getter、equals & hashCodetoString

    package work.basil.example.orders;
    
    import java.util.UUID;
    
    public record Order(UUID id , String customerName)
    {
    }
    

    定义DayManager 类。

    构造函数是为跟踪订单设置数据结构的地方。你在你的 addOrder 方法中做这项工作,这是没有意义的。

    构造函数的目标是填充一个NavigableMap,一个Map,它维护它的键是一个排序的顺序。我们使用TreeMap作为NavigableMap接口的具体实现。

    我们地图的键是ZonedDateTime,这是一个在时区范围内带有时间的日期。每个ZonedDateTime 对象是每个时隙的开始。我使用这种方法而不是你仅仅使用整数来识别每个插槽。

    我们地图的值是Order 对象的列表。当我们将订单添加到我们的跟踪系统时,它们会出现在这些列表之一中。每个列表都绑定到一个ZonedDateTime 对象,作为我们地图中的时隙。使用List 的问题在于该类是一个可调整大小的集合。所以我们的代码在这里管理大小限制,检查当前大小以计算列表中已经存在多少订单。我们将该计数与我们在DayManager 类中作为成员字段保留的每时隙容量数进行比较。

    • 如果我们的产能不足,我们将订单添加到列表中,并返回一个包含ZonedDateTimeOptional 来标识时间段。
    • 如果我们有足够的能力,我们需要进入下一个时间段 - 我把这个留给读者作为练习。
      • 提示:我们手头有一个ZonedDateTime,这是用于访问我们地图的当前密钥。因此,如果我们添加存储为成员字段的Duration,我们将获得映射中的下一个键。使用该键获取下一个订单列表。 Lather, rinse, repeat,直到超过一天的最后一个时间段。

    顺便说一句,在实际工作中,我会寻找第三方库,例如 Eclipse CollectionsGoogle Guava 以获得固定大小的列表类。最好依赖已经编写和测试过的代码,而不是依赖我们这里的大小检查代码。

    我们在构造函数中使用时隙和空列表预先填充我们的地图。因此,当我们开始添加订单时,我们就有了一个数据结构。

    addOrder 方法在映射中查找请求的时隙作为键。在地图上执行get 会返回List 的订单供我们检查。

    package work.basil.example.orders;
    
    import java.time.*;
    import java.util.*;
    
    public class DayManager
    {
        // Member fields.
        final ZoneId zoneId;
        final LocalDate workDate;
        final LocalTime startTime;
        final Duration timeSlice;
        final int numberOfTimeSlots, capacityPerTimeSlot;
        private final NavigableMap < ZonedDateTime, List < Order > > ordersPerTimeSlot;
    
        // Constructor
        public DayManager ( final ZoneId zoneId , final LocalDate localDate , final LocalTime startTime , final Duration timeSlice , final int numberOfTimeSlots , final int capacityPerSlot )
        {
            this.zoneId = zoneId;
            this.workDate = localDate;
            this.startTime = startTime;
            this.timeSlice = timeSlice;
            this.numberOfTimeSlots = numberOfTimeSlots;
            this.capacityPerTimeSlot = capacityPerSlot;
    
            this.ordersPerTimeSlot = new TreeMap <>();
            this.populateMap();
        }
    
        // Subroutine.
        private void populateMap ( )
        {
            ZonedDateTime start = ZonedDateTime.of( this.workDate , this.startTime , this.zoneId );
            for ( int i = 0 ; i < this.numberOfTimeSlots ; i++ )
            {
                Duration d = this.timeSlice.multipliedBy( i );
                ZonedDateTime zdt = start.plus( d );
                List < Order > list = new ArrayList <>( this.capacityPerTimeSlot );
                this.ordersPerTimeSlot.put( zdt , list );
            }
            System.out.println( "this.ordersPerTimeSlot = " + this.ordersPerTimeSlot );
        }
    
        // Business logic.
        public Optional < ZonedDateTime > addOrder ( final Order order , final ZonedDateTime zdt )
        {
            List < Order > orders = this.ordersPerTimeSlot.get( zdt );
            if ( Objects.isNull( orders ) ) { return Optional.empty(); }
            if ( orders.size() > this.capacityPerTimeSlot )
            {
                String msg = "ERROR - Capacity per time slot exceeded. ";
                System.out.println( msg );
                throw new IllegalStateException( msg );
            } else if ( orders.size() == this.capacityPerTimeSlot )
            {
                String msg = "INFO - This time slot filled.";
                System.out.println( msg );
                throw new IllegalStateException( msg );
            } else if ( orders.size() < this.capacityPerTimeSlot )
            {
                // Room in this time slot to place order.
                orders.add( order );
                return Optional.of( zdt );
            } else
            {
                String msg = "ERROR - Should never reach this point. Error in IF-THEN logic of adding orders.";
                System.out.println( msg );
                throw new IllegalStateException( msg );
            }
        }
    
        // Debugging
        public String dumpOrders ( )
        {
            return this.ordersPerTimeSlot.toString();
        }
    }
    

    这是一个App 课程,用于练习我们的DayManagerOrder 课程。

    package work.basil.example.orders;
    
    import java.time.*;
    import java.util.Optional;
    import java.util.UUID;
    
    public class App
    {
        public static void main ( String[] args )
        {
            ZoneId z = ZoneId.of( "America/Edmonton" );
            LocalDate ld = LocalDate.of( 2022 , Month.JANUARY , 23 );
            DayManager dm = new DayManager( z , ld , LocalTime.of( 13 , 0 ) , Duration.ofHours( 1 ) , 3 , 3 );
    
            Order order = new Order( UUID.fromString( "2d8e5cc2-26ac-474d-a081-2c71207fd6c5" ) , "Basil" );
            Optional < ZonedDateTime > optionalTimeSlot = dm.addOrder( order , ZonedDateTime.of( ld , LocalTime.of( 14 , 0 ) , z ) );
    
            System.out.println( "order = " + order );
            System.out.println( "optionalTimeSlot.toString() = " + optionalTimeSlot );
            System.out.println( dm.dumpOrders() );
        }
    }
    

    运行时。

    this.ordersPerTimeSlot = {2022-01-23T13:00-07:00[America/Edmonton]=[], 2022-01-23T14:00-07:00[America/Edmonton]=[], 2022-01-23T15:00-07:00[America/Edmonton]=[]}
    order = Order[id=2d8e5cc2-26ac-474d-a081-2c71207fd6c5, customerName=Basil]
    optionalTimeSlot.toString() = Optional[2022-01-23T14:00-07:00[America/Edmonton]]
    {2022-01-23T13:00-07:00[America/Edmonton]=[], 2022-01-23T14:00-07:00[America/Edmonton]=[Order[id=2d8e5cc2-26ac-474d-a081-2c71207fd6c5, customerName=Basil]], 2022-01-23T15:00-07:00[America/Edmonton]=[]}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-20
      • 1970-01-01
      • 2014-08-04
      • 1970-01-01
      • 1970-01-01
      • 2012-05-02
      • 2016-07-24
      • 2013-08-18
      相关资源
      最近更新 更多