我确实花了太长时间才决定使用哈希映射来缓存结果。
我的策略不是使用单例哈希图,而是使用单例通用对象类存储静态缓存实例。我没有看到加载具有过多哈希树分支级别的单个哈希图的原因。
减少哈希解析量
如果我知道我正在处理的对象是 Employee、Address、Project,我将创建三个静态哈希
final static private Map<Long, Employee> employeeCache =
new HashMap<Long, Employee>();
final static private Map<Long, Address> addressCache =
new HashMap<Long, Address>();
final static private Map<String name, Project> projectCache =
new HashMap<String name, Project>();
public static void putEmployee(Long id, Employee emp){
employeeCache.put(id, emp);
}
public static Employee getEmployee(Long id){
return employeeCache.get(id);
}
public static void putEmployee(Long id, Address addr){
addressCache.put(id, addr);
}
public static Address getEmployee(Long id){
return addressCache.get(id);
}
public static void putProject(String name, Address addr){
projectCache.put(name, addr);
}
public static Address getProject(String name){
return projectCache.get(name);
}
把它全部放在一张地图上会很麻烦。有效访问和存储数据的原则是 - 您确定的有关数据的信息越多,您就越应该利用您拥有的信息来隔离该数据。它将降低访问数据所需的哈希分辨率级别。更不用说需要完成的所有风险和不确定的类型转换。
如果可以,请避免散列
如果您知道 CurrentEmployee 和 NextEmployee 始终只有一个值,请避免将它们存储在 Employee 的散列中。只需创建静态实例
Employee CurrentEmployee, NextEmployee;
这将完全避免需要任何哈希解析。
避免污染全局命名空间
如果可能,将它们保留为类实例而不是静态实例,以避免污染全局命名空间。
为什么要避免污染全局命名空间?因为,由于全局命名空间混淆,多个类会无意中使用相同的名称,从而导致无数错误。
将缓存保持在最接近预期或使用位置的位置
如果可能,如果缓存主要用于某个类,请将缓存保留为该类中的类实例。并为另一个类需要从该缓存中获取数据的任何罕见实例提供事件总线事件。
这样你就会有一个预期的模式
ZZZManager.getZZZ(id);
如果可能,完成缓存,
否则/并通过提供推杆和吸气剂将其私有化。不要让另一个类无意中重新实例化缓存,特别是如果有一天你的类变成了一个通用实用程序库。putter 和 getter 也有机会通过直接向缓存提供缓存无法处理的键或值来验证请求,以避免请求清除缓存或将应用程序推入异常。
将这些原则转化为 Javascript 本地存储
GWT 页面说
明智地使用命名约定有助于处理存储数据。例如,在名为 MyWebApp 的 Web 应用程序中,与名为 Stock 的 UI 表中的行关联的键值数据可能具有前缀为 MyWebApp.Stock 的键名。
因此,用相当粗略的代码补充你的类中的 HashMap,
public class EmployeePresenter {
Storage empStore = Storage.getLocalStorageIfSupported();
HashMap<Long, Employee> employeeCache;
public EmployeePresenter(){
if (empStore==null) {
employeeCache = new HashMap<Employee>();
}
}
private String getPrefix(){
return this.getClass()+".Employee";
//return this.getClass().getCanonicalName()+".Employee";
}
public Employee putEmployee(Long id, Employee employee)
if (empStore==null) {
stockStore.setItem(getPrefix()+id, jsonEncode(employee));
return;
}
employeeCache.put(id, employee);
}
public Employee getEmployee(Long id)
if (empStore==null) {
return (Employee) jsonDecode(Employee.class, stockStore.getItem(getPrefix()+id));
}
return employeeCache(id);
}
}
由于 localstore 仅基于字符串,我假设您将编写自己的 json 编码器解码器。另一方面,为什么不直接将 json 从回调中接收到 store 中呢?
内存限制?
我不能自称在这个问题上的专业知识,但我预测哈希图的答案是浏览器上操作系统限制的最大内存。减去浏览器、插件和 javascript 等已经消耗的所有内存等开销。
对于 HTML5 本地存储,GWT 页面说
“LocalStorage:每个浏览器每个应用程序 5MB。根据 HTML5 规范,用户可以在需要时增加此限制;但是,只有少数浏览器支持此功能。”
“SessionStorage:仅受系统内存限制”