Java根据时间范围判断有效数据
Java determine valid data depending on a time range
确定指定日期有效属性值的最佳方法是什么?
table 看起来像这样:
Attribute name
Value
valid from
attr1
41
01.01.2020
attr1
41,123
02.02.2021
attr1
41,456
02.02.2023
例如。如果日期是 13.06.2021,则有效值应为 41,123
第二种情况是当多一行可用时:
Attribute name
Value
valid from
valid to
attr1
41
01.01.2020
01.01.2100
attr1
41,123
02.02.2021
02.04.2021
attr1
41,456
02.02.2023
01.01.2100
在这种情况下,有效值应为 41
由于您只提供了数据而没有提供代码,我们假设您有一个包含 Attribute
个元素的列表,如下所示(简化):
class Attribute {
String name;
double value;
LocalDate validFrom;
LocalDate validTo;
}
理想情况下,您可以为每个按 validFrom
排序的属性名称维护一个树图,例如Map<String, SortedMap<LocalDate, Attribute>>
.
然后获取属性名称的排序映射,根据相关日期获取尾部或头部映射并迭代。假设您已按 validFrom
降序对地图进行排序,它可能如下所示:
Map<String, SortedMap<LocalDate, Attribute>> attribs = ....;
LocalDate targetDate = LocalDate.now();
//get the map for "attr1" or an empty map if there isn't one
Iterator<Attribute> itr = attribs.getOrDefault("attr1", Collections.emptySortedMap())
.tailMap( targetDate )
.values()
.iterator();
//since we have descending order we're first checking the entries that have become valid last
//so just continue until you hit one that hasn't become invalid already or you run out of entries
while(itr.hasNext()) {
Attribute attr = itr.next();
if(!attr.validTo.isBefore(targetDate )) {
return attr.value;
}
}
//no value found, could also return an empty Optional
return null;
如果您没有这样的地图,也可以使用流来完成,但对于重复查找来说效率会更低:
List<Attribute> attribs = ...;
LocalDate targetDate = LocalDate.now();
OptionalDouble value =
attribs.stream()
.filter(a -> a.name.equals("attrib1")) //remove all other attribs
.filter(a -> !a.validFrom.isAfter(targetDate)) //remove all that not yet valid
.filter(a -> !a.validTo.isBefore(targetDate)) //remove all that aren't valid anymore
.sorted(Comparator.comparing(a -> a.validFrom).reverseOrder()) //sort by validFrom in descending order to get the latest
.mapToDouble(a -> a.value) //extract the value
.findFirst(); //pick the first value if one exists
确定指定日期有效属性值的最佳方法是什么?
table 看起来像这样:
Attribute name | Value | valid from |
---|---|---|
attr1 | 41 | 01.01.2020 |
attr1 | 41,123 | 02.02.2021 |
attr1 | 41,456 | 02.02.2023 |
例如。如果日期是 13.06.2021,则有效值应为 41,123
第二种情况是当多一行可用时:
Attribute name | Value | valid from | valid to |
---|---|---|---|
attr1 | 41 | 01.01.2020 | 01.01.2100 |
attr1 | 41,123 | 02.02.2021 | 02.04.2021 |
attr1 | 41,456 | 02.02.2023 | 01.01.2100 |
在这种情况下,有效值应为 41
由于您只提供了数据而没有提供代码,我们假设您有一个包含 Attribute
个元素的列表,如下所示(简化):
class Attribute {
String name;
double value;
LocalDate validFrom;
LocalDate validTo;
}
理想情况下,您可以为每个按 validFrom
排序的属性名称维护一个树图,例如Map<String, SortedMap<LocalDate, Attribute>>
.
然后获取属性名称的排序映射,根据相关日期获取尾部或头部映射并迭代。假设您已按 validFrom
降序对地图进行排序,它可能如下所示:
Map<String, SortedMap<LocalDate, Attribute>> attribs = ....;
LocalDate targetDate = LocalDate.now();
//get the map for "attr1" or an empty map if there isn't one
Iterator<Attribute> itr = attribs.getOrDefault("attr1", Collections.emptySortedMap())
.tailMap( targetDate )
.values()
.iterator();
//since we have descending order we're first checking the entries that have become valid last
//so just continue until you hit one that hasn't become invalid already or you run out of entries
while(itr.hasNext()) {
Attribute attr = itr.next();
if(!attr.validTo.isBefore(targetDate )) {
return attr.value;
}
}
//no value found, could also return an empty Optional
return null;
如果您没有这样的地图,也可以使用流来完成,但对于重复查找来说效率会更低:
List<Attribute> attribs = ...;
LocalDate targetDate = LocalDate.now();
OptionalDouble value =
attribs.stream()
.filter(a -> a.name.equals("attrib1")) //remove all other attribs
.filter(a -> !a.validFrom.isAfter(targetDate)) //remove all that not yet valid
.filter(a -> !a.validTo.isBefore(targetDate)) //remove all that aren't valid anymore
.sorted(Comparator.comparing(a -> a.validFrom).reverseOrder()) //sort by validFrom in descending order to get the latest
.mapToDouble(a -> a.value) //extract the value
.findFirst(); //pick the first value if one exists