【问题标题】:Efficiently search a list of consecutive date periods有效地搜索连续日期期间的列表
【发布时间】:2018-05-03 14:21:34
【问题描述】:

我有一个包含连续时间段(没有重叠)和某个值的结构。

class Record {
    private TimeWindow timeWindow;
    private String value;
}

interface TimeWindow {
    LocalDate getBeginDate();

    LocalDate getEndDate(); //Can be null
}

我的目标是实现一个获取日期并计算出值的函数。 一个简单的实现可能是遍历所有记录,直到日期与窗口匹配。

class RecordHistory {
    private List<Record> history;

    public String getValueForDate(LocalDate date) {
        for (Record record : history) {
            if (record.dateMatchesWindow(date)){
                return record.getValue();
            }
        }

        return null; //or something similar
    }
}

class Record {

    private TimeWindow timeWindow;
    private String value;

    public boolean dateMatchesWindow(LocalDate subject) {
        return !subject.isBefore(timeWindow.getBeginDate()) && (timeWindow.getEndDate() == null || !subject.isAfter(timeWindow.getEndDate()));
    }

    public String getValue(){
        return value;
    }
}

这些值的来源来自数据库查询(没有机会更改表的结构)。记录列表可能很小也可能很大,并且从历史开始到结束的日期各不相同。但是,对于相同的 RecordHistory,相同的日期不会计算两次。会有多个 RecordHistory 对象,值代表不同的属性。

有没有一种有效的方法来搜索这个结构?

【问题讨论】:

  • 让数据库帮你搜索?
  • 索引您的表并让数据库执行搜索
  • 不幸的是,数据库更改不是一种选择

标签: java performance search


【解决方案1】:

您可以使用binary search 在 O(logn) 时间内获取匹配的Record(如果存在这样的记录)。

Java 已经有数据结构可以为您做到这一点,例如TreeMap。您可以将每个Record 映射到它的开始时间,然后获取给定时间的floorEntry,看看它是否匹配。

// create map (done only once, of course)
TreeMap<LocalDate, Record> records = new TreeMap<>();
for (Record r : recordList) {
    records.put(r.getTimeWindow().getBeginDate(), r);
}

// find record for a given date
public String getValueForDate(LocalDate date) {
    Record floor = records.floorEntry(date).getValue();
    if (floor.dateMatchesWindow(date)) {
        return r;
    }
    return null;
}

如果条目不重叠,并且如果楼层条目匹配,则不会有其他条目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 2020-05-03
    • 1970-01-01
    • 2021-08-19
    相关资源
    最近更新 更多