首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >创建具有两个数组列表的订单插槽系统

创建具有两个数组列表的订单插槽系统
EN

Stack Overflow用户
提问于 2021-03-22 01:06:31
回答 1查看 108关注 0票数 0

我需要给一位日管理人员写信,为一家餐厅的订单分配时间。

这就是白天经理:

代码语言:javascript
运行
复制
public DayManager (LocalDate date, int numberOfTimeSlots, int capacityPerSlot) {
        this.date = date;
        this.capacityPerSlot = capacityPerSlot;
        this.numberOfTimeSlots = numberOfTimeSlots;

对于每一天,我可以选择可用时隙的数量和每个时隙的容量(因此,如果我选择3个时隙,每个时隙的容量为3个,总共是9个时隙)。

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

这是我的一堂课,用来补充订单:

代码语言:javascript
运行
复制
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列表,另外,我也不知道如何才能得到下一个最低的插槽号。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-22 03:34:11

多机

你可以用多机Map是导致值的键对。在multimap中,值实际上是值的集合,而不是单个值。

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

  • 2022-01-23T13:00-07:00美国/埃德蒙顿
    • []

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

  • 2022-01-23T15:00-07:00美国/埃德蒙顿
    • []

(次要细节:2d8e5cc2-26ac-474d-a081-2c71207fd6c5文本是用于标识特定顺序的128位UUID值的十六进制字符串表示。)

示例代码

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

首先,定义我们的Order类。我们将使用Java16中的新特性使其成为记录。您也可以定义一个常规类,但是记录要短得多。编译器隐式地创建构造函数、getter、equals & hashCodetoString

代码语言:javascript
运行
复制
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类中作为成员字段保留的每个时隙容量进行比较。

  • 如果容量不足,则将订单添加到列表中,并返回包含ZonedDateTimeZonedDateTime以标识时隙。
  • 如果我们有能力,我们需要转到我离开的下一个- this时段,作为读者的练习。
    • 提示:我们手头有一个ZonedDateTime,当前用于访问地图的密钥。因此,如果我们将存储为成员字段的Duration添加进来,我们将在映射中获得下一个密钥。用这个键得到下一个订单列表。泡沫,冲洗,重复,直到一天中最后一段时间过去。

顺便说一句,在实际工作中,我会查看第三方库,比如日食收藏谷歌番石榴,以获得一个固定大小的列表类。与其依赖我们这里的大小检查代码,不如依赖已经编写和测试的代码。

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

addOrder方法在地图中查找请求的时隙作为键。在地图上执行get将返回命令的List,以便我们进行检查。

代码语言:javascript
运行
复制
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类。

代码语言:javascript
运行
复制
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() );
    }
}

跑的时候。

代码语言:javascript
运行
复制
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]=[]}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66739162

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档