欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于倒排索引的缓存对象索引通用解决方案 博客分类: java java倒排索引 

程序员文章站 2024-02-24 20:29:10
...

一个给javabean列表建立倒排索引的通用类,主要可用于给缓存中的一类对象添加索引便于搜索,对于缓存中的对象实现模糊搜索是一种非常合适的方案

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class InvertedIndexGeneric<T> {
	/**
	 * 索引
	 */
	private Map<String, List<T>> invertedIndex = new HashMap<String, List<T>>();
	/**
	 * 缓存的待索引项
	 */
	private Map<String, T> invertedIndexItemsMap = new HashMap<String, T>();

	/**
	 * 主键属性的get方法
	 */
	private Method prekeyMethod;
	/**
	 * 被索引属性的get方法
	 */
	private Method indexedAttrMethod;

	private Class<T> beanClass;

	/**
	 * 
	 * @param beanList
	 *            待索引javabean列表
	 * @param targetBeanClass
	 *            待索引javabean类型
	 * @param preKeyAttr
	 *            待索引项唯一标识(主键)的javabean属性名
	 * @param indexedAttr
	 *            待索引项的附加索引的javabean属性名
	 */
	public InvertedIndexGeneric(List<T> beanList, Class<T> targetBeanClass,
			String preKeyAttr, String indexedAttr) {
		if (beanList == null || beanList.size() == 0) {
			throw new RuntimeException("待索引项为空!");
		}
		this.beanClass = targetBeanClass;
		this.prekeyMethod = this.buildAttrGetMethod(preKeyAttr);
		this.indexedAttrMethod = this.buildAttrGetMethod(indexedAttr);
		for (T invertedIndexAble : beanList) {
			invertedIndexItemsMap
					.put(this.getIndexedBeanPrekey(invertedIndexAble),
							invertedIndexAble);
		}
		this.buildInverteIndex();
	}

	/**
	 * 查询键值相关的索引项
	 * 
	 * @param key
	 *            关键字
	 * @return 键值相关的索引项
	 */
	public synchronized List<T> find(String key) {
		return invertedIndex.get(key);
	}

	/**
	 * 增加待索引项
	 * 
	 * @param item
	 *            待索引项
	 */
	public synchronized void addInvertItem(T item) {
		List<String> keys = getAllKeys(this.getIndexedAttrValue(item));
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			List<T> linkedIndexAbles = invertedIndex.get(key);
			if (linkedIndexAbles != null) {
				for (T varIndexAble : linkedIndexAbles) {
					if (varIndexAble.equals(item)) {
						continue;
					}
				}
				linkedIndexAbles.add(item);
			} else {
				List<T> indexAbles = new ArrayList<T>();
				indexAbles.add(item);
				invertedIndex.put(key, indexAbles);
			}
		}
	}

	/**
	 * 删除待索引项
	 * 
	 * @param beanPreKey
	 *            可索引项的主键
	 */
	public synchronized void deleteInvertedItem(String beanPreKey) {
		T invertedIndexAble = invertedIndexItemsMap.get(beanPreKey);
		List<String> keys = getAllKeys(this
				.getIndexedAttrValue(invertedIndexAble));
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			List<T> linkedIndexAbles = invertedIndex.get(key);
			if (linkedIndexAbles != null && linkedIndexAbles.size() > 0) {
				for (T varTItem : linkedIndexAbles) {
					if (this.getIndexedBeanPrekey(varTItem).equals(beanPreKey)) {
						linkedIndexAbles.remove(varTItem);
						break;
					}
				}
			}
			if (linkedIndexAbles.size() <= 0) {
				invertedIndex.remove(key);
			}
		}
	}

	/**
	 * 更新可索引项
	 * 
	 * @param bean
	 *            可索引项
	 */
	public synchronized void updateInvertedItem(T bean) {
		T oldItem = invertedIndexItemsMap.get(this.getIndexedBeanPrekey(bean));
		if (oldItem != null) {
			this.deleteInvertedItem(this.getIndexedBeanPrekey(oldItem));
			this.addInvertItem(bean);
		}
	}

	/**
	 * 构建索引
	 */
	private synchronized void buildInverteIndex() {
		for (T bean : invertedIndexItemsMap.values()) {
			this.addInvertItem(bean);
		}
	}

	/**
	 * 找出一个字符串所有的可能的倒排索引的键列表
	 * 
	 * @param str
	 *            字符串
	 * @return 一个字符串所有的可能的倒排索引的键列表
	 */
	private List<String> getAllKeys(String str) {
		List<String> result = new ArrayList<String>();
		char[] chars = str.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			String key = "";
			for (int j = i; j < chars.length; j++) {
				key = key + chars[j];
				result.add(key);
			}
		}
		return result;
	}

	private String getIndexedBeanPrekey(T bean) {
		try {
			return this.prekeyMethod.invoke(bean).toString();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private String getIndexedAttrValue(T bean) {
		try {
			return this.indexedAttrMethod.invoke(bean).toString();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private Method buildAttrGetMethod(String attrName) {
		String firstLetter = attrName.substring(0, 1);
		firstLetter = firstLetter.toUpperCase();
		String methodName = "get" + firstLetter + attrName.substring(1);
		Method method = null;
		try {
			method = this.beanClass.getMethod(methodName);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return method;
	}
}

 

相关标签: java 倒排索引