如何在 ObservableList 中使用 LocalTime 添加缺失的时间?
How can I add the missing time using LocalTime in ObservableList?
我正在尝试创建一个日程安排,我只能在其中获取输入的时间和日程名称。
我想把时间表放在 List
但如果没有其他时间表,如果没有其他早期时间,列表应该添加一个从 6:00 AM
开始的新空时间表。
我有 ObservableList<DataClass>
,它包含 LocalTime
和一些 String
。
示例 1:
假设列表包含 3 个项目:
[04:00 AM] [Some String]
[06:30 AM] [Some String]
[05:00 PM] [Some String]
我想将列表中缺少的时间从 4:00 AM
添加到 5:00 PM
,因此列表将是:
[04:00 AM] [Some String]
[05:00 AM] [Some String]
[06:30 AM] [Some String]
[07:00 AM] [Some String]
[08:00 AM] [Some String]
[09:00 AM] [Some String]
[10:00 AM] [Some String]
[11:00 AM] [Some String]
[12:00 PM] [Some String]
[01:00 PM] [Some String]
[02:00 PM] [Some String]
[03:00 PM] [Some String]
[04:00 PM] [Some String]
[05:00 PM] [Some String]
示例 2:
假设列表包含 2 个项目:
[08:30 AM] [Some String]
[02:00 PM] [Some String]
我想将列表中缺少的时间从 6:00 AM
添加到 5:00 PM
,因此列表将是:
[06:00 AM] [Some String]
[07:00 AM] [Some String]
[08:00 AM] [Some String]
[09:00 AM] [Some String]
[10:00 AM] [Some String]
[11:00 AM] [Some String]
[12:00 PM] [Some String]
[01:00 PM] [Some String]
[02:00 PM] [Some String]
[03:00 PM] [Some String]
[04:00 PM] [Some String]
[05:00 PM] [Some String]
示例 3:
假设列表包含 1 个项目:
[08:00 PM] [Some String]
我想将6:00 AM
到8:00 PM
列表中缺失的时间补上,这样列表就可以了。
[06:00 AM] [Some String]
[07:00 AM] [Some String]
[08:00 AM] [Some String]
[09:00 AM] [Some String]
[10:00 AM] [Some String]
[11:00 AM] [Some String]
[12:00 PM] [Some String]
[01:00 PM] [Some String]
[02:00 PM] [Some String]
[03:00 PM] [Some String]
[04:00 PM] [Some String]
[05:00 PM] [Some String]
[06:00 PM] [Some String]
[07:00 PM] [Some String]
[08:00 PM] [Some String]
如果没有其他较早的时间,时间应该从06:00 AM
开始,否则时间将从那个较早的时间开始。
如果没有其他时间,时间应该在5:00 PM
结束,否则时间将在那个特定时间结束,我只想添加HOUR
像increment
小时所以不应该有6:30
、5:30
,除非是手动输入的。
我正在考虑以下逻辑,但由于思路锁定无法继续。
Sort the list base on the time from AM to PM to get the first time
Check if the time of the first data is equal or less than 6:00 AM
if true, then start from that time and continue adding the missing
time until the 5:00 PM or the last time is reach.
if false, then
start from 6:00 AM and continue adding the missing time until the 5:00
PM or the last time is reach.
下面的代码是我目前所拥有的并且令人费解。
private void fillTheList(){
ObservableList<DataClass> data = FXCollections.observableArrayList();
Comparator<DataClass> comparator = Comparator.comparing(DataClass::getLocalTime);
data.add(new DataClass(convertTime("05:00 PM"), "Sample Content"));
data.add(new DataClass(convertTime("06:30 AM"), "Sample Content"));
FXCollections.sort(data,comparator); //Sort the list from AM to PM
for (DataClass list : data){
if(list.getLocalTime().isBefore(LocalTime.of(6,0))){
//The time is less than 6:00 AM then it should start here and Add the missing time but I don't know what to do next...
}else{
//the time is not less than 6:00 AM... I don't know what to do next..
}
}
FXCollections.sort(data,comparator); //Sort the list from AM to PM again
}
private LocalTime convertTime(String timeString){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a");
return LocalTime.parse(timeString, formatter);
}
PS:我实际上不确定我要问什么,所以如有必要,请随时提出修改建议。
更新:DataClass.class
public class DataClass {
private LocalTime localTime;
private String content;
public DataClass(LocalTime localTime, String content){
this.localTime = localTime;
this.content = content;
}
public LocalTime getLocalTime(){
return localTime;
}
public String getContent(){
return content;
}
}
您必须遵循这些步骤
获取开始的值,它将是06AM
或列表的第一个值,这取决于哪个是第一个
得到end的值,就是第二个值
- 清除列表以删除开始值和结束值
- 遍历 2 之间的所有日期,每次递增 1 小时
- 结束条件是
i.isBefore(end.plusHours(1))
而不是 i.isBefore(end)
因为您需要包含 end
元素
- 排序并打印
ObservableList<DataClass> data = FXCollections.observableArrayList();
Comparator<DataClass> comparator = Comparator.comparing(DataClass::getLocalTime);
data.add(new DataClass(convertTime("05:00 PM"), "Sample Content"));
data.add(new DataClass(convertTime("06:30 AM"), "Sample Content"));
FXCollections.sort(data,comparator); //Sort the list from AM to PM
// 1. & 2.
LocalTime begin = LocalTime.of(6,0);
if(data.get(0).getLocalTime().isBefore(begin)){
begin = data.get(0).getLocalTime();
}
LocalTime end = LocalTime.of(17,0);
if(end.isBefore(data.get(data.size()-1).getLocalTime())){
end = data.get(data.size()-1).getLocalTime();
}
// 3.
data.clear();
// 4. & 5.
for(LocalTime i = begin.withMinute(0); !i.isAfter(end); i = i.plusHours(1)){
data.add(new DataClass(i, "Sample Content"));
}
// 6.
FXCollections.sort(data,comparator); //Sort the list from AM to PM again
System.out.println(data);
// [06:00, 07:00, 08:00, 09:00, 10:00, 11:00, 12:00, 13:00, 14:00, 15:00, 16:00, 17:00]
不太确定您需要什么,但这可能是您需要的:
ObservableList<DataClass> data = FXCollections.observableArrayList();
// Need to specify the period that you want the entries to be filled
private void fill(LocalTime from, LocalTime to) {
// Keep adding new entries until we have reached the end
while (!from.isAfter(to)) {
// We need a final variable for stream()
final LocalTime temp = from;
// If data does not contain any time that is equivalent to this time
if (data.stream().noneMatch(d -> temp.equals(d.getLocalTime()))) {
data.add(new DataClass(temp, "Hello World"));
}
// Increment the time by an hour, and wait for next loop cycle
from = from.plusHours(1);
}
}
除非您想以排序的方式显示数据,否则排序没有任何意义。
更新
此实现不会阻止您传递具有分钟(或秒)值的 from
和 to
。
如果需要纯小时单位,可以改成:
ObservableList<DataClass> data = FXCollections.observableArrayList();
// Need to specify the period that you want the entries to be filled
private void fill(int fromHour, int toHour) {
LocalTime from = LocalTime.of(fromHour, 0);
LocalTime to = LocalTime.of(toHour, 0);
// Keep adding new entries until we have reached the end
while (!from.isAfter(to)) {
// We need a final variable for stream()
final LocalTime temp = from;
// If data does not contain any time that is equivalent to this time
if (data.stream().noneMatch(d -> temp.equals(d.getLocalTime()))) {
data.add(new DataClass(temp, "Hello World"));
}
// Increment the time by an hour, and wait for next loop cycle
from = from.plusHours(1);
}
}
这将强制两个边界值只有小时值。
进行如下操作
- 对列表进行排序
- 设置可能需要插入的时间(从插入范围的下界开始)
- 找到第一个时间>=要插入时间的元素的索引
- 如果元素的时间与要插入的时间不匹配,则在该索引处插入一个新元素
- 修改要插入的时间,如果没有离开插入范围则继续3.
ObservableList<DataClass> data = ...
LocalTime lowerBound = LocalTime.of(6, 0); // or some other input
LocalTime upperBound = LocalTime.of(12 + 5, 0); // or some other input
Comparator<DataClass> comparator = Comparator.comparing(DataClass::getLocalTime);
FXCollections.sort(data, comparator);
int size = data.size();
int index = 0;
while (!lowerBound.isAfter(upperBound)) {
// find inserting index
while (index < size && data.get(index).getLocalTime().isBefore(lowerBound)) {
index++;
}
// insert, if not already in list
if (index >= size || !data.get(index).getLocalTime().equals(lowerBound)) {
data.add(index, new DataClass(lowerBound, "Inserted"));
size++;
}
lowerBound = lowerBound.plusHours(1);
index++;
}
请注意,对于列表中较小的步骤和较大数量的元素,代码的性能不是最理想的,因为添加到列表的中间在 O(n)
中运行,因此最终的复杂度将是 O(i + i*n + n*log(n))
其中 i
是插入次数,n
是列表的初始大小。
为了改善这一点,您可以将所有新元素添加到列表的末尾,然后使用 mergesort 的合并步骤一次,这将导致运行时 O(i+n*log(n))
:
final int size = data.size();
int index = 0;
while (!lowerBound.isAfter(upperBound)) {
// find inserting index
while (index < size && data.get(index).getLocalTime().isBefore(lowerBound)) {
index++;
}
// insert, if not already in list
if (index >= size || !data.get(index).getLocalTime().equals(lowerBound)) {
data.add(new DataClass(lowerBound, "Inserted"));
} else {
index++;
}
lowerBound = lowerBound.plusHours(1);
}
// merge
DataClass[] merged = new DataClass[data.size()];
int insertionIndex = 0;
int index1 = 0;
int index2 = size;
while (index1 < size && index2 < merged.length) {
DataClass v1 = data.get(index1);
DataClass v2 = data.get(index2);
if (v2.getLocalTime().isBefore(v1.getLocalTime())) {
merged[insertionIndex] = v2;
index2++;
} else {
merged[insertionIndex] = v1;
index1++;
}
insertionIndex++;
}
// copy remaining
while (index1 < size) {
merged[insertionIndex++] = data.get(index1++);
}
while (index2 < merged.length) {
merged[insertionIndex++] = data.get(index2++);
}
data.setAll(merged);
你自己也很好。此外,azro 是正确的,您需要通过与数据中已有的最短时间和最长时间进行比较,找到要考虑插入的最短时间和最长时间。 Jai 是正确的,您应该在插入之前检查时间是否已经在列表中,并且流对于此目的很方便。我的版本使用 int
来迭代几个小时,但所有其他版本都是正确的,LocalTime
也有效。
int minHour = 6;
int maxHour = 17;
if (! data.isEmpty()) {
// adjust min and max from list contents
int minExisintgHour = data.get(0).getLocalTime().getHour();
if (minExisintgHour < minHour) {
// if the list already contained 4:00 or 4:30,
// we only need to add hours from 5, so add 1
minHour = minExisintgHour + 1;
}
int maxExisintgHour = data.get(data.size() - 1).getLocalTime().getHour();
if (maxExisintgHour > maxHour) {
maxHour = maxExisintgHour;
}
}
for (int hour = minHour; hour <= maxHour; hour++) {
LocalTime time = LocalTime.of(hour, 0);
boolean alreadyInData = data.stream().anyMatch(d -> d.getLocalTime().equals(time));
if (! alreadyInData) {
data.add(new DataClass(time, "Added beacuse time was missing"));
}
}
我假设您在问题中对上述代码前后的列表进行排序。如果您对最小值和最大值进行线性遍历(一些流也可以这样做),则可以省略之前的排序。
示例结果列表:
[06:00 AM] [Added beacuse time was missing]
[06:30 AM] [Sample Content]
[07:00 AM] [Added beacuse time was missing]
[08:00 AM] [Added beacuse time was missing]
[09:00 AM] [Added beacuse time was missing]
[10:00 AM] [Added beacuse time was missing]
[11:00 AM] [Added beacuse time was missing]
[12:00 PM] [Added beacuse time was missing]
[01:00 PM] [Added beacuse time was missing]
[02:00 PM] [Added beacuse time was missing]
[03:00 PM] [Added beacuse time was missing]
[04:00 PM] [Added beacuse time was missing]
[05:00 PM] [Sample Content]
我正在尝试创建一个日程安排,我只能在其中获取输入的时间和日程名称。
我想把时间表放在 List
但如果没有其他时间表,如果没有其他早期时间,列表应该添加一个从 6:00 AM
开始的新空时间表。
我有 ObservableList<DataClass>
,它包含 LocalTime
和一些 String
。
示例 1: 假设列表包含 3 个项目:
[04:00 AM] [Some String]
[06:30 AM] [Some String]
[05:00 PM] [Some String]
我想将列表中缺少的时间从 4:00 AM
添加到 5:00 PM
,因此列表将是:
[04:00 AM] [Some String]
[05:00 AM] [Some String]
[06:30 AM] [Some String]
[07:00 AM] [Some String]
[08:00 AM] [Some String]
[09:00 AM] [Some String]
[10:00 AM] [Some String]
[11:00 AM] [Some String]
[12:00 PM] [Some String]
[01:00 PM] [Some String]
[02:00 PM] [Some String]
[03:00 PM] [Some String]
[04:00 PM] [Some String]
[05:00 PM] [Some String]
示例 2: 假设列表包含 2 个项目:
[08:30 AM] [Some String]
[02:00 PM] [Some String]
我想将列表中缺少的时间从 6:00 AM
添加到 5:00 PM
,因此列表将是:
[06:00 AM] [Some String]
[07:00 AM] [Some String]
[08:00 AM] [Some String]
[09:00 AM] [Some String]
[10:00 AM] [Some String]
[11:00 AM] [Some String]
[12:00 PM] [Some String]
[01:00 PM] [Some String]
[02:00 PM] [Some String]
[03:00 PM] [Some String]
[04:00 PM] [Some String]
[05:00 PM] [Some String]
示例 3: 假设列表包含 1 个项目:
[08:00 PM] [Some String]
我想将6:00 AM
到8:00 PM
列表中缺失的时间补上,这样列表就可以了。
[06:00 AM] [Some String]
[07:00 AM] [Some String]
[08:00 AM] [Some String]
[09:00 AM] [Some String]
[10:00 AM] [Some String]
[11:00 AM] [Some String]
[12:00 PM] [Some String]
[01:00 PM] [Some String]
[02:00 PM] [Some String]
[03:00 PM] [Some String]
[04:00 PM] [Some String]
[05:00 PM] [Some String]
[06:00 PM] [Some String]
[07:00 PM] [Some String]
[08:00 PM] [Some String]
如果没有其他较早的时间,时间应该从06:00 AM
开始,否则时间将从那个较早的时间开始。
如果没有其他时间,时间应该在5:00 PM
结束,否则时间将在那个特定时间结束,我只想添加HOUR
像increment
小时所以不应该有6:30
、5:30
,除非是手动输入的。
我正在考虑以下逻辑,但由于思路锁定无法继续。
Sort the list base on the time from AM to PM to get the first time
Check if the time of the first data is equal or less than 6:00 AM
if true, then start from that time and continue adding the missing time until the 5:00 PM or the last time is reach.
if false, then start from 6:00 AM and continue adding the missing time until the 5:00 PM or the last time is reach.
下面的代码是我目前所拥有的并且令人费解。
private void fillTheList(){
ObservableList<DataClass> data = FXCollections.observableArrayList();
Comparator<DataClass> comparator = Comparator.comparing(DataClass::getLocalTime);
data.add(new DataClass(convertTime("05:00 PM"), "Sample Content"));
data.add(new DataClass(convertTime("06:30 AM"), "Sample Content"));
FXCollections.sort(data,comparator); //Sort the list from AM to PM
for (DataClass list : data){
if(list.getLocalTime().isBefore(LocalTime.of(6,0))){
//The time is less than 6:00 AM then it should start here and Add the missing time but I don't know what to do next...
}else{
//the time is not less than 6:00 AM... I don't know what to do next..
}
}
FXCollections.sort(data,comparator); //Sort the list from AM to PM again
}
private LocalTime convertTime(String timeString){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a");
return LocalTime.parse(timeString, formatter);
}
PS:我实际上不确定我要问什么,所以如有必要,请随时提出修改建议。
更新:DataClass.class
public class DataClass {
private LocalTime localTime;
private String content;
public DataClass(LocalTime localTime, String content){
this.localTime = localTime;
this.content = content;
}
public LocalTime getLocalTime(){
return localTime;
}
public String getContent(){
return content;
}
}
您必须遵循这些步骤
获取开始的值,它将是
06AM
或列表的第一个值,这取决于哪个是第一个得到end的值,就是第二个值
- 清除列表以删除开始值和结束值
- 遍历 2 之间的所有日期,每次递增 1 小时
- 结束条件是
i.isBefore(end.plusHours(1))
而不是i.isBefore(end)
因为您需要包含end
元素 - 排序并打印
ObservableList<DataClass> data = FXCollections.observableArrayList();
Comparator<DataClass> comparator = Comparator.comparing(DataClass::getLocalTime);
data.add(new DataClass(convertTime("05:00 PM"), "Sample Content"));
data.add(new DataClass(convertTime("06:30 AM"), "Sample Content"));
FXCollections.sort(data,comparator); //Sort the list from AM to PM
// 1. & 2.
LocalTime begin = LocalTime.of(6,0);
if(data.get(0).getLocalTime().isBefore(begin)){
begin = data.get(0).getLocalTime();
}
LocalTime end = LocalTime.of(17,0);
if(end.isBefore(data.get(data.size()-1).getLocalTime())){
end = data.get(data.size()-1).getLocalTime();
}
// 3.
data.clear();
// 4. & 5.
for(LocalTime i = begin.withMinute(0); !i.isAfter(end); i = i.plusHours(1)){
data.add(new DataClass(i, "Sample Content"));
}
// 6.
FXCollections.sort(data,comparator); //Sort the list from AM to PM again
System.out.println(data);
// [06:00, 07:00, 08:00, 09:00, 10:00, 11:00, 12:00, 13:00, 14:00, 15:00, 16:00, 17:00]
不太确定您需要什么,但这可能是您需要的:
ObservableList<DataClass> data = FXCollections.observableArrayList();
// Need to specify the period that you want the entries to be filled
private void fill(LocalTime from, LocalTime to) {
// Keep adding new entries until we have reached the end
while (!from.isAfter(to)) {
// We need a final variable for stream()
final LocalTime temp = from;
// If data does not contain any time that is equivalent to this time
if (data.stream().noneMatch(d -> temp.equals(d.getLocalTime()))) {
data.add(new DataClass(temp, "Hello World"));
}
// Increment the time by an hour, and wait for next loop cycle
from = from.plusHours(1);
}
}
除非您想以排序的方式显示数据,否则排序没有任何意义。
更新
此实现不会阻止您传递具有分钟(或秒)值的 from
和 to
。
如果需要纯小时单位,可以改成:
ObservableList<DataClass> data = FXCollections.observableArrayList();
// Need to specify the period that you want the entries to be filled
private void fill(int fromHour, int toHour) {
LocalTime from = LocalTime.of(fromHour, 0);
LocalTime to = LocalTime.of(toHour, 0);
// Keep adding new entries until we have reached the end
while (!from.isAfter(to)) {
// We need a final variable for stream()
final LocalTime temp = from;
// If data does not contain any time that is equivalent to this time
if (data.stream().noneMatch(d -> temp.equals(d.getLocalTime()))) {
data.add(new DataClass(temp, "Hello World"));
}
// Increment the time by an hour, and wait for next loop cycle
from = from.plusHours(1);
}
}
这将强制两个边界值只有小时值。
进行如下操作
- 对列表进行排序
- 设置可能需要插入的时间(从插入范围的下界开始)
- 找到第一个时间>=要插入时间的元素的索引
- 如果元素的时间与要插入的时间不匹配,则在该索引处插入一个新元素
- 修改要插入的时间,如果没有离开插入范围则继续3.
ObservableList<DataClass> data = ...
LocalTime lowerBound = LocalTime.of(6, 0); // or some other input
LocalTime upperBound = LocalTime.of(12 + 5, 0); // or some other input
Comparator<DataClass> comparator = Comparator.comparing(DataClass::getLocalTime);
FXCollections.sort(data, comparator);
int size = data.size();
int index = 0;
while (!lowerBound.isAfter(upperBound)) {
// find inserting index
while (index < size && data.get(index).getLocalTime().isBefore(lowerBound)) {
index++;
}
// insert, if not already in list
if (index >= size || !data.get(index).getLocalTime().equals(lowerBound)) {
data.add(index, new DataClass(lowerBound, "Inserted"));
size++;
}
lowerBound = lowerBound.plusHours(1);
index++;
}
请注意,对于列表中较小的步骤和较大数量的元素,代码的性能不是最理想的,因为添加到列表的中间在 O(n)
中运行,因此最终的复杂度将是 O(i + i*n + n*log(n))
其中 i
是插入次数,n
是列表的初始大小。
为了改善这一点,您可以将所有新元素添加到列表的末尾,然后使用 mergesort 的合并步骤一次,这将导致运行时 O(i+n*log(n))
:
final int size = data.size();
int index = 0;
while (!lowerBound.isAfter(upperBound)) {
// find inserting index
while (index < size && data.get(index).getLocalTime().isBefore(lowerBound)) {
index++;
}
// insert, if not already in list
if (index >= size || !data.get(index).getLocalTime().equals(lowerBound)) {
data.add(new DataClass(lowerBound, "Inserted"));
} else {
index++;
}
lowerBound = lowerBound.plusHours(1);
}
// merge
DataClass[] merged = new DataClass[data.size()];
int insertionIndex = 0;
int index1 = 0;
int index2 = size;
while (index1 < size && index2 < merged.length) {
DataClass v1 = data.get(index1);
DataClass v2 = data.get(index2);
if (v2.getLocalTime().isBefore(v1.getLocalTime())) {
merged[insertionIndex] = v2;
index2++;
} else {
merged[insertionIndex] = v1;
index1++;
}
insertionIndex++;
}
// copy remaining
while (index1 < size) {
merged[insertionIndex++] = data.get(index1++);
}
while (index2 < merged.length) {
merged[insertionIndex++] = data.get(index2++);
}
data.setAll(merged);
你自己也很好。此外,azro 是正确的,您需要通过与数据中已有的最短时间和最长时间进行比较,找到要考虑插入的最短时间和最长时间。 Jai 是正确的,您应该在插入之前检查时间是否已经在列表中,并且流对于此目的很方便。我的版本使用 int
来迭代几个小时,但所有其他版本都是正确的,LocalTime
也有效。
int minHour = 6;
int maxHour = 17;
if (! data.isEmpty()) {
// adjust min and max from list contents
int minExisintgHour = data.get(0).getLocalTime().getHour();
if (minExisintgHour < minHour) {
// if the list already contained 4:00 or 4:30,
// we only need to add hours from 5, so add 1
minHour = minExisintgHour + 1;
}
int maxExisintgHour = data.get(data.size() - 1).getLocalTime().getHour();
if (maxExisintgHour > maxHour) {
maxHour = maxExisintgHour;
}
}
for (int hour = minHour; hour <= maxHour; hour++) {
LocalTime time = LocalTime.of(hour, 0);
boolean alreadyInData = data.stream().anyMatch(d -> d.getLocalTime().equals(time));
if (! alreadyInData) {
data.add(new DataClass(time, "Added beacuse time was missing"));
}
}
我假设您在问题中对上述代码前后的列表进行排序。如果您对最小值和最大值进行线性遍历(一些流也可以这样做),则可以省略之前的排序。
示例结果列表:
[06:00 AM] [Added beacuse time was missing]
[06:30 AM] [Sample Content]
[07:00 AM] [Added beacuse time was missing]
[08:00 AM] [Added beacuse time was missing]
[09:00 AM] [Added beacuse time was missing]
[10:00 AM] [Added beacuse time was missing]
[11:00 AM] [Added beacuse time was missing]
[12:00 PM] [Added beacuse time was missing]
[01:00 PM] [Added beacuse time was missing]
[02:00 PM] [Added beacuse time was missing]
[03:00 PM] [Added beacuse time was missing]
[04:00 PM] [Added beacuse time was missing]
[05:00 PM] [Sample Content]