我需要给一位日管理人员写信,为一家餐厅的订单分配时间。
这就是白天经理:
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列表,另外,我也不知道如何才能得到下一个最低的插槽号。
发布于 2021-03-22 03:34:11
多机
你可以用多机。Map
是导致值的键对。在multimap中,值实际上是值的集合,而不是单个值。
例如,设想一个由三个时隙组成的层次结构,其中第一个和最后一个时隙包含一个空列表(还没有订单),而中间时隙有一个单订单列表。
(次要细节:2d8e5cc2-26ac-474d-a081-2c71207fd6c5
文本是用于标识特定顺序的128位UUID值的十六进制字符串表示。)
示例代码
下面是一些示例代码。这个代码是不完整的,但是会让你朝着正确的方向前进。
首先,定义我们的Order
类。我们将使用Java16中的新特性使其成为记录。您也可以定义一个常规类,但是记录要短得多。编译器隐式地创建构造函数、getter、equals
& hashCode
和toString
。
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
类中作为成员字段保留的每个时隙容量进行比较。
ZonedDateTime
的ZonedDateTime
以标识时隙。ZonedDateTime
,当前用于访问地图的密钥。因此,如果我们将存储为成员字段的Duration
添加进来,我们将在映射中获得下一个密钥。用这个键得到下一个订单列表。泡沫,冲洗,重复,直到一天中最后一段时间过去。顺便说一句,在实际工作中,我会查看第三方库,比如日食收藏或谷歌番石榴,以获得一个固定大小的列表类。与其依赖我们这里的大小检查代码,不如依赖已经编写和测试的代码。
我们在构造函数中预先填充了时隙和空列表。因此,当我们开始添加订单时,我们就有了一个数据结构。
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]=[]}
https://stackoverflow.com/questions/66739162
复制相似问题