mybatis核心数据结构详解——CacheKey

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<Object> updateList;

	public CacheKey() {
		this.hashcode = DEFAULT_HASHCODE;
		this.multiplier = DEFAULT_MULTIPLYER;
		this.count = 0;
		this.updateList = new ArrayList<Object>();
	}


}

multiplier:乘数,是一个常数,为37(质数)

hashCode:当前CacheKey对象的hash值,通过组合中每个对象迭代计算得出。初始值为17(质数)

checksum:检验和,组合中每个对象的原始hashCode的和

count:当前组合中对象的个数

updateList:此List保存当前组合中所有的对象

CacheKey既然一般要作为HashMap的key存在,那必然要有hashCode()方法和equals(Object)方法,那么它是如何实现这两个方法的呢?

  1. 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对象不相等。

发布了535 篇原创文章 · 获赞 2985 · 访问量 248万+

猜你喜欢

转载自blog.csdn.net/dataiyangu/article/details/104828044