使用不同参数查询缓存的有效方法

时间:2014-07-11 08:30:55

标签: java caching hashmap

这是我试图解决的用例的示例问题。 在数据库中有一个表格,它在两个地方之间旅行时每天消耗的时间,这个表格中等,即有5万个条目。所以我们想在这个表周围缓存以减少数据库负载。因此,问题陈述是返回在特定日期到达地点X和Y之间的时间。

同样的查询可以多次执行,因此我们需要在实施解决方案时留出空间。

下面是我的实现我删除了从DB中获取数据以删除混乱的代码。为简化起见,您可以假设该表有4列 Travelled_date,from,to,Time_taken。

缓存有两个暴露给最终用户的方法来获取时间,当用户从/到/和日期获取时间时,我当前实现中存在问题。在这里我每次创建TravelledPlaces的对象,我做了不可变但但后来用相同的参数调用缓存将创建多个TravelledPlaces对象,这会占用主内存。是否有任何建议可以避免同一次调用此对象的多次创建?

以下是代码

public class TimeConsumedCache {

private Map<Date, Map<TravelledPlaces, Double>> timeCache = new HashMap<Date, Map<TravelledPlaces, Double>>();

public double getTimeTravelled(Date date, TravelledPlaces tp) {
    return timeCache.get(date).get(tp);
}

public double getTimeTravelled(Date date, String from, String to) {
    return timeCache.get(date).get(new TravelledPlaces(from, to));
}

private static final class TravelledPlaces {
    private String fromLocation;
    private String toLocation;

    public TravelledPlaces(String fromLocation, String toLocation) {
        this.fromLocation = fromLocation;
        this.toLocation = toLocation;
    }

    //hashcode and equals removed for brevity

}

  }

如果我直接使用

怎么样
  timeCache.get(date).get(from + to)); and change cache definition to 
  Map<Date, Map<String, Double>>  but this loses the object oriented approach of  dealing with the problem

1 个答案:

答案 0 :(得分:1)

  

每次创建我制作的TravelledPlaces对象   不可变但后续调用具有相同参数的缓存   创建多个TravelledPlaces对象,这将耗尽主内存

这是一个不正确的假设。

return timeCache.get(date).get(new TravelledPlaces(from, to));

不会吃掉记忆。用于查询的对象将被垃圾收集。我可以假设一个不错的优化,内存开销将接近一个对象的大小。

一个问题可能来自timeCache的大小。连续添加从零到50k的元素将需要增加容器容量。

如果以惰性方式构建缓存,只有在缺少元素时才添加元素,这些成本将被分摊。如果由于任何原因你必须预先构建整个缓存,那么我建议只使用一个地图和

class DatedTravelledPlaces
{
   private Date date;
   private TravelledPlaces places;

    DatedTravelledPlaces(Date date, String from, String to)
    {
      //construction
    }

    @Override
    public int hashCode() {
      //same as what you did with TravelledPlaces 
    }

    @Override
    public boolean equals(Object obj) {
      //same as what you did with TravelledPlaces 
    }
}

public class TimeConsumedCache {
    private Map<DatedTravelledPlaces, double> timeCache;


     TimeConsumedCache()
     {
       int dbsize = computeDBSize();
       timeCache = new HashMap<DatedTravelledPlaces, double>(dbsize );
     }

}