CacheKey(org.apache.ibatis.cache.CacheKey),缓存键。目的是为若干个被缓存对象的组合(有顺序)生成一个key,来唯一标识这个组合。一般用作HashMap<CacheKey,Object>,作为Map对象的key存在。
CacheKey还可以在对象创建后,通过update(Object)方法或updateAll(Object[])方法,动态地向组合中追加对象(内部会通过迭代更新key值)。
CacheKey的数据结构如下:
package org.apache.ibatis.cache;import java.io.Serializable;import java.lang.reflect.Array;import java.util.ArrayList;import java.util.List;/** * Cache缓存对象的key * 在HashMap中, 通过hashCode()和equals()标识key的唯一性 * * 计算公式:hashcode=multiplier * hashcode + object.hashCode()*count * @author Administrator * */public class CacheKey implements Cloneable, Serializable { private static final long serialVersionUID = 1146682552656046210L; public static final CacheKey NULL_CACHE_KEY = new NullCacheKey(); private static final int DEFAULT_MULTIPLYER = 37; private static final int DEFAULT_HASHCODE = 17; // 乘数,固定初始值质数37,不会变 private int multiplier; // 当前hashCode值,初始值是质数17, // 计算公式:hashcode=hashcode * multiplier + object.hashCode()*count private int hashcode; // 所有更新对象的初始hashCode的和 private long checksum; // 更新的对象总数 private int count; // 更新的对象集合 private List
multiplier:乘数,是一个常数,为37(质数)
hashCode:当前CacheKey对象的hash值,通过组合中每个对象迭代计算得出。初始值为17(质数)
checksum:检验和,组合中每个对象的原始hashCode的和
count:当前组合中对象的个数
updateList:此List保存当前组合中所有的对象
CacheKey既然一般要作为HashMap的key存在,那必然要有hashCode()方法和equals(Object)方法,那么它是如何实现这两个方法的呢?
hashCode():
直接返回对象中保存的hashCode的值。hashCode的迭代公式如下:
hashCode = hashCode * multiplier + object.hashCode() * count
每次迭代一个新的对象时,count会首先+1,然后迭代hashCode值。
迭代过程的源码如下:
private void doUpdate(Object object) { // 如果object为null则hashCode为1 // 不为null则调用hashCode()获取 int baseHashCode = object == null ? 1 : object.hashCode(); // count+1 count++; // checksum+此对象hashCode checksum += baseHashCode; baseHashCode *= count; // 重新计算hashCode hashcode = multiplier * hashcode + baseHashCode; // 更新列表中添加此对象 updateList.add(object); }
2.equals(Object):
判断两个CacheKey对象相等的充分必要条件是,两个对象代表的组合序列中的每个元素必须都相等(调用equals方法返回true)。但是,为了避免每次比较都要进行一次循环(遍历组合List),CacheKey采用以下顺序进行比较:
hashCode-->checksum-->count-->updateList
比较过程中,有一个不相等,则视为两个CacheKey对象不相等。