快照的数据结构

时间:2014-01-23 23:33:59

标签: java algorithm data-structures map

我需要能够在一段时间内将对象存储在数据结构中,然后能够获取特定时间数据的快照。我有一些解决方案,但我想知道是否有更优化的方法来做到这一点。我想可能有一种方法可以优化存储机制,以便不需要迭代每个元素来获取当时的快照。

在实际情况中,可以随时更新数据。数据结构中的对象由Integers索引。我用Map快速模拟了一些东西来说明我想要做的事情(arraylist是对象更新的历史)。

public class TimeStoreTest {

    static SimpleDateFormat df = new SimpleDateFormat("yy-MM-dd HH:mm:ss");

    public static void main(String[] args) throws Exception {

        Date[] dates = new Date[] { df.parse("2014-01-23 10:30:30"),
                df.parse("14-01-23 10:33:30"), df.parse("14-01-23 10:36:30"),
                df.parse("14-01-23 10:39:30"), df.parse("14-01-23 10:42:30") };

        Map<Integer, List<SimpleObject>> timeStore = new HashMap<Integer, List<SimpleObject>>();

        for (int i = 0; i < 10; i += 2) {
            List<SimpleObject> objs = new ArrayList<SimpleObject>();

            objs.add(new SimpleObject(i, dates[0]));
            timeStore.put(i, objs);
        }

        for (int i = 1; i < 10; i += 2) {
            List<SimpleObject> objs = new ArrayList<SimpleObject>();

            objs.add(new SimpleObject(i, dates[1]));
            timeStore.put(i, objs);
        }

        for (int i = 0; i < 10; i += 2) {
            List<SimpleObject> objs = timeStore.get(i);
            objs.add(new SimpleObject(i, dates[2]));
        }

        for (int i = 1; i < 10; i += 2) {
            List<SimpleObject> objs = timeStore.get(i);
            objs.add(new SimpleObject(i, dates[3]));
        }

        for (int i = 5; i < 10; i++) {
            List<SimpleObject> objs = timeStore.get(i);
            objs.add(new SimpleObject(i, dates[4]));
        }

        System.out.println("Current Data Store: ");
        for (Entry<Integer, List<SimpleObject>> entry : timeStore.entrySet()) {
            System.out.println(entry);
        }

        Date queryDate = df.parse("14-01-23 10:31:00");

        System.out.println("Query for object snapshot @ " + queryDate);
        for (SimpleObject obj : getObjectsAtTime(queryDate, timeStore)) {
            System.out.println(obj);
        }

        queryDate = df.parse("14-01-23 10:34:30");
        System.out.println("Query for object snapshot @ " + queryDate);
        for (SimpleObject obj : getObjectsAtTime(queryDate, timeStore)) {
            System.out.println(obj);
        }

        queryDate = df.parse("14-01-23 10:39:30");
        System.out.println("Query for object snapshot @ " + queryDate);
        for (SimpleObject obj : getObjectsAtTime(queryDate, timeStore)) {
            System.out.println(obj);
        }

        queryDate = df.parse("14-01-23 10:42:00");

        System.out.println("Query for object snapshot @ " + queryDate);
        for (SimpleObject obj : getObjectsAtTime(queryDate, timeStore)) {
            System.out.println(obj);
        }

        queryDate = df.parse("14-01-23 10:45:00");

        System.out.println("Query for object snapshot @ " + queryDate);
        for (SimpleObject obj : getObjectsAtTime(queryDate, timeStore)) {
            System.out.println(obj);
        }

    }

    public static List<SimpleObject> getObjectsAtTime(Date date,
            Map<Integer, List<SimpleObject>> store) {
        List<SimpleObject> objectsAtTime = new ArrayList<SimpleObject>();

        for (Entry<Integer, List<SimpleObject>> entry : store.entrySet()) {

            SimpleObject previousObject = null;

            List<SimpleObject> list = entry.getValue();

            for (int i = 0; i < list.size(); i++) {
                SimpleObject currentObject = list.get(i);
                if (previousObject != null) {
                    if (date.after(previousObject.updatedTime)
                            && date.before(currentObject.updatedTime)) {
                        objectsAtTime.add(previousObject);
                        break;
                    } else if (currentObject.updatedTime.equals(date)) {
                        objectsAtTime.add(currentObject);
                        break;
                    } else if (i == list.size() - 1
                            && date.after(previousObject.updatedTime)) {
                        objectsAtTime.add(currentObject);
                    }
                }

                previousObject = currentObject;
            }

        }

        return objectsAtTime;

    }
}

class SimpleObject implements Comparable {
    int id;
    Date updatedTime;

    public SimpleObject(int id, Date updatedTime) {
        this.id = id;
        this.updatedTime = new Date(updatedTime.getTime());

    }

    @Override
    public String toString() {
        return "(object id=" + id + "; t="
                + TimeStoreTest.df.format(updatedTime) + ")";
    }

    @Override
    public int compareTo(Object object) {
        // TODO Auto-generated method stub
        return updatedTime.compareTo(((SimpleObject) object).updatedTime);
    }
}

结果:

当前数据存储:

0=[(object id=0; t=14-01-23 10:30:30), (object id=0; t=14-01-23 10:36:30)]
1=[(object id=1; t=14-01-23 10:33:30), (object id=1; t=14-01-23 10:39:30)]
2=[(object id=2; t=14-01-23 10:30:30), (object id=2; t=14-01-23 10:36:30)]
3=[(object id=3; t=14-01-23 10:33:30), (object id=3; t=14-01-23 10:39:30)]
4=[(object id=4; t=14-01-23 10:30:30), (object id=4; t=14-01-23 10:36:30)]
5=[(object id=5; t=14-01-23 10:33:30), (object id=5; t=14-01-23 10:39:30), (object id=5; t=14-01-23 10:42:30)]
6=[(object id=6; t=14-01-23 10:30:30), (object id=6; t=14-01-23 10:36:30), (object id=6; t=14-01-23 10:42:30)]
7=[(object id=7; t=14-01-23 10:33:30), (object id=7; t=14-01-23 10:39:30), (object id=7; t=14-01-23 10:42:30)]
8=[(object id=8; t=14-01-23 10:30:30), (object id=8; t=14-01-23 10:36:30), (object id=8; t=14-01-23 10:42:30)]
9=[(object id=9; t=14-01-23 10:33:30), (object id=9; t=14-01-23 10:39:30), (object id=9; t=14-01-23 10:42:30)]
Query for object snapshot @ Thu Jan 23 10:31:00 PST 2014
(object id=0; t=14-01-23 10:30:30)
(object id=2; t=14-01-23 10:30:30)
(object id=4; t=14-01-23 10:30:30)
(object id=6; t=14-01-23 10:30:30)
(object id=8; t=14-01-23 10:30:30)
Query for object snapshot @ Thu Jan 23 10:34:30 PST 2014
(object id=0; t=14-01-23 10:30:30)
(object id=1; t=14-01-23 10:33:30)
(object id=2; t=14-01-23 10:30:30)
(object id=3; t=14-01-23 10:33:30)
(object id=4; t=14-01-23 10:30:30)
(object id=5; t=14-01-23 10:33:30)
(object id=6; t=14-01-23 10:30:30)
(object id=7; t=14-01-23 10:33:30)
(object id=8; t=14-01-23 10:30:30)
(object id=9; t=14-01-23 10:33:30)
Query for object snapshot @ Thu Jan 23 10:39:30 PST 2014
(object id=0; t=14-01-23 10:36:30)
(object id=1; t=14-01-23 10:39:30)
(object id=2; t=14-01-23 10:36:30)
(object id=3; t=14-01-23 10:39:30)
(object id=4; t=14-01-23 10:36:30)
(object id=5; t=14-01-23 10:39:30)
(object id=6; t=14-01-23 10:36:30)
(object id=7; t=14-01-23 10:39:30)
(object id=8; t=14-01-23 10:36:30)
(object id=9; t=14-01-23 10:39:30)
Query for object snapshot @ Thu Jan 23 10:42:00 PST 2014
(object id=0; t=14-01-23 10:36:30)
(object id=1; t=14-01-23 10:39:30)
(object id=2; t=14-01-23 10:36:30)
(object id=3; t=14-01-23 10:39:30)
(object id=4; t=14-01-23 10:36:30)
(object id=5; t=14-01-23 10:39:30)
(object id=6; t=14-01-23 10:36:30)
(object id=7; t=14-01-23 10:39:30)
(object id=8; t=14-01-23 10:36:30)
(object id=9; t=14-01-23 10:39:30)
Query for object snapshot @ Thu Jan 23 10:45:00 PST 2014
(object id=0; t=14-01-23 10:36:30)
(object id=1; t=14-01-23 10:39:30)
(object id=2; t=14-01-23 10:36:30)
(object id=3; t=14-01-23 10:39:30)
(object id=4; t=14-01-23 10:36:30)
(object id=5; t=14-01-23 10:42:30)
(object id=6; t=14-01-23 10:42:30)
(object id=7; t=14-01-23 10:42:30)
(object id=8; t=14-01-23 10:42:30)
(object id=9; t=14-01-23 10:42:30)

所以,你可以看到它有效,但我正试图找到提高效率的方法。

3 个答案:

答案 0 :(得分:1)

使用NavigableMap可能会让您的生活更轻松。请查看TreeMap#floorEntry()处的示例,该示例与您的getObjectsAtTime方法类似。

它还有其他方法,例如subMap也可能很方便。

答案 1 :(得分:1)

好像你可以使用TreeMap然后调用subMap来查询你想要的日期范围

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.NavigableMap;
import java.util.TreeMap;


public class KeyRange {

  static SimpleDateFormat df = new SimpleDateFormat("yy-MM-dd HH:mm:ss");

  public static void main(String[] args) throws Exception {

    Date[] dates = new Date[]{df.parse("2014-01-23 10:30:30"),
      df.parse("14-01-23 10:33:30"), df.parse("14-01-23 10:36:30"),
      df.parse("14-01-23 10:39:30"), df.parse("14-01-23 10:42:30")};
/**
 * use a treeMap, because it has sorted keys and it can be queried with from -> to values
 */
    TreeMap<Date, Object> data = new TreeMap<>();
    for(Date d : dates){
      data.put(d, null);
    }
    /**
     * use the subMap function to "query" the map by a range of sorted keys...this would be your query time span
     */
    NavigableMap<Date, Object> queryResult = data.subMap(df.parse("14-01-23 10:33:30"), true,  df.parse("14-01-23 10:39:30"), false);
    System.out.println(queryResult);
  }
}

上面的结果就是这个

{Thu 1月23日10:33:30 EST 2014 = null,Thu 1月23日10:36:30 EST 2014 = null}

如果您希望它按降序排序,则将.descendingMap()添加到子图方法的末尾

答案 2 :(得分:0)

我最终选择了一个区间树(http://en.wikipedia.org/wiki/Interval_tree),每个段都被映射到当时活动的对象的HashMap。

我为我的用法修改了这段代码:

https://github.com/KevinStern/software-and-algorithms/blob/master/src/main/java/blogspot/software_and_algorithms/stern_library/data_structure/DynamicIntervalTree.java