当前位置: 首页 > 知识库问答 >
问题:

创建具有2个数组列表的订单槽系统

萧英睿
2023-03-14

我需要写一个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();
            }
            
    

我需要帮助的是:

每一个新的订单,我都需要检查是否还有剩余的容量在客户首选的插槽。如果还有空位,我就把那个空位分配给他。如果该插槽中没有剩余的容量,我将为该插槽分配下一个最低的索引(和可用容量)。如果那天没有剩余的容量,我干脆什么也不回。

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

共有1个答案

樊飞飙
2023-03-14

你可以用多地图。映射是指向值键对。在multimap中,值实际上是值的集合,而不是单个值。

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

  • 2022-01-23T13:00-07:00“美/埃德蒙顿”
    • []
    • [订单[ID=2D8E5CC2-26AC-474D-A081-2C71207FD6C5,客户名=Basil]]
    • []

    (小细节:2D8E5CC2-26AC-474D-A081-2C71207FD6C5文本是用于标识特定顺序的128位UUID值的十六进制字符串表示形式。)

    下面是一些示例代码。这段代码是不完整的,但将使您朝着正确的方向前进。

    首先,定义我们的order类。我们将使它成为一个记录,使用新的功能在Java 16。你可以定义一个常规的类,但是一个记录要简单得多。编译器隐式创建构造函数、getters、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,这是一个在时区上下文中具有time-of-day的日期。每个zoneddatetime对象是每个时隙的开始。我使用这种方法,而不是仅仅使用整数来标识每个插槽。

    映射的值是order对象的列表。当我们将订单添加到我们的跟踪系统中时,它们就会出现在其中一个列表中。每个列表都绑定到一个zoneddatetime对象,作为映射中的时隙。使用list的问题在于类是一个可调整大小的集合。因此,这里的代码管理大小限制,检查当前大小以获得列表中已有多少订单的计数。我们将该计数与作为DayManager类的成员字段保留的每时隙容量数进行比较。

    • 如果容量不足,则将订单添加到列表中,并返回一个optional,其中包含ZonedDateTime以标识时隙。
    • 如果我们已经排满了,我们需要进入下一个时间段-- ,这是我留给读者的练习。
      • 提示:我们手头有一个ZonedDateTime,用于访问映射的当前密钥。因此,如果我们添加存储为成员字段的duration,我们将获得映射中的下一个键。使用该键获取下一个订单列表。起泡,冲洗,重复,直到一天中的最后一个时间段。

      顺便说一下,在实际工作中,我会使用第三方库(如Eclipse Collections或Google 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类,用于执行我们的DayManager&Order类。

      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]=[]}
      

 类似资料:
  • 对于我的任务,我需要创建一个订单系统,该系统根据空闲容量分配时隙。我可以选择插槽数和每个插槽的容量(因此,如果我有3个插槽,每个插槽有3个容量,那么总共是9个插槽)。 每个客户在订单中说明他们的首选时隙(这里是0、1或2)。 我需要检查是否还有剩余的容量在他们想要的插槽,然后我才能下订单。如果有剩余的容量,我分配他们的首选插槽。如果没有剩余的容量,我会给他们分配一个下一个最低索引的插槽给他们的首选

  • 问题内容: 我想要创建一个arraylist数组,如下所示: 但是它没有编译。我怎样才能做到这一点? 问题答案: 根据Oracle文档: “你不能创建参数化类型的数组” 相反,你可以执行以下操作: 正如汤姆·霍廷(Tom Hawting)的建议-定位线一样,最好这样做:

  • 问题内容: 我有以下代码片段,我不明白为什么它不起作用: 有人能指出我正确的方向吗? 我已经看到JonSkeet在另一个问题上的回答,但是那里的最后一个示例对我来说不起作用。即使我将强制类型转换添加到标记为的行或行中,也会出现编译错误。 问题答案: 您始终可以通过明确指定type参数来告诉Java您想要列表:

  • 问题内容: 我正在使用PHP。 我有以下具有关系数据(父子关系)的数组。 我需要采用这种JSON格式: 我知道我需要创建一个多维数组并通过json_encode()运行它。我还认为,用于此操作的此方法必须是递归的,因为现实世界中的数据可能具有未知数量的级别。 我很高兴展示我的一些方法,但是它们没有用。 谁能帮我? 我被要求分享我的工作。这是我尝试过的方法,但还没有达到我所不知道的帮助程度。 我做了

  • 如何创建一个列表,其中的值介于我输入的两个值之间?例如,为11到16之间的值生成以下列表:

  • 问题内容: 我想创建一个numpy数组,其中每个元素必须是一个列表,因此以后我可以向每个元素追加新元素。 我已经看过谷歌,这里已经有堆栈溢出,但是似乎找不到地方。 主要问题是numpy假定您的列表必须成为数组,但这不是我要的。 问题答案: 如您所见,在给出类似以下内容时,尝试创建2d数组 您已应用了一些技巧来解决此默认行为。 一种是使子列表的长度可变。它不能从这些数组中生成2d数组,因此它求助于对