基于倒排索引的缓存对象索引通用解决方案 博客分类: java java倒排索引
程序员文章站
2024-02-24 19:58:46
...
一个给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; } }