【问题标题】:Data Structure for Snapshots at Time时间快照的数据结构
【发布时间】:2014-01-23 23:33:59
【问题描述】:

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

在实际场景中,数据的更新可以随时进行。数据结构中的对象由整数索引。我用 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)

所以,你可以看到它是有效的,但我正在努力寻找提高效率的方法。

【问题讨论】:

    标签: java algorithm data-structures map


    【解决方案1】:

    使用 NavigableMap 可能会让您的生活更轻松。看看TreeMap#floorEntry() 的例子,它的作用类似于你的getObjectsAtTime 方法。

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

    【讨论】:

    • 感谢您的提示。这看起来可以很好地替代 ArrayList 本身,但是有没有办法在整个数据集中利用它?
    • 如果您在给定时间内有多个条目,恐怕您需要坚持使用 ArrayList 作为值...这个想法是用 TreeMap 替换您的 HashMap。
    【解决方案2】:

    好像你可以使用 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);
      }
    }
    

    上面的结果是这样的

    {2014 年 1 月 23 日星期四 10:33:30 EST=null,2014 年 1 月 23 日星期四 10:36:30 EST=null}

    如果要降序排序,则将 .descendingMap() 添加到 submap 方法的末尾

    【讨论】:

      【解决方案3】:

      【讨论】:

        猜你喜欢
        • 2013-06-25
        • 2012-07-24
        • 1970-01-01
        • 1970-01-01
        • 2019-11-11
        • 1970-01-01
        • 2013-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多