主题:规则引擎开发规范--规则配置类规范<连载4>

2.1. 内存表的索引处理机制
内存表是多行数据的存储,一般访问内存表时,都是通过遍历方式对内存表进行访问,然后逐行进行判断和处理。这种方式一般情况下都是遍历完整个内存表的数据后,才返回退出。
但是某些情况下,我们可能只需要找到某一列的值为特定的值时做相应的处理,这种情况下遍历太消耗性能。
因此我们可以事先为这个内存表指定某个列作为关键字建立索引。下次访问时,可以先根据关键字找到对应的行。然后进行处理。索引采用HashMap进行实现,会极大的提高性能。
根据实际的需要,我们将索引设计成三种类型:分为唯一索引、链表多索引、key-value多索引。这三种实现可以在一个内存表中同时存在,但是同一种实现,只能存在一种。
一种是单个关键字的唯一索引,唯一索引是有点项主键的意思,某列的值是唯一的。采用HashMap<Object,int>来存储索引,int为行号。使用这种类型的索引,主要有以下的方法:
resetKeyMap 创建唯一索引,传入参数为关键字所在的列号
moveToKey 查找并定位根据唯一索引找到的行: 传入参数为需要匹配的值。 根据这个方法就能定位到关键字所在行,然后进行修改
以下的方法中,如果该字段设置了唯一关键字会调用:
findFirstByKey 相当于map来使用,找第一列为传入值的,返回第二列的值。没有关键字初始化的话,则遍历
exitsKey 是否在指定的列,存在等于传入值的行。没有关键字唯一索引初始化的话,则遍历
getValueByKey 和findFirstByKey类似,只是第二个参数传入了指定的关键字所在列和返回值所在列
updateFirstByKey 将指定的关键字为第一传入值的行的指定列的值,变更为第二传入值,第三参数为指定了关键字所在列和返回值所在列。如果存在关键字唯一索引,则从索引中取,否则遍历。
第二种索引实现是单一关键字的多索引,可以将多列拼接成一个字符串,作为单一关键字。这种索引在建立索引时,需要使用initKeyListMap方法指定那几列是索引项,并且指定拼接字符。索引会将这些列的值转成字符串然后用拼接字符得到一个字符串后,作为key值放到HashMap<String,List>中。下次要使用时,必须将需要访问的值也采用拼接字符,拼接成一个新的字符串后,使用findKeyList方法进行调用。
initKeyListMap(int):传入值为索引所在的列号,根据该列创建多索引
initKeyListMap(string,string):传入值为关键字所在的列,以及拼接使用的连接符。关键字所在列可以多个,用,隔开,可以使列号或者列名
findKeyList(string),根据传入的值,找到关键字为传入值的,多个索引
nextKeyList():根据索引找到了多行之后,可以依次取得下一行
第三种索引实现了多关键字的多索引。这种方式的关键字,是采用HashMap<Object,HashMap>方式存储的,也就是索引下面再找索引
multiKeyReset(int):根据传入的列号,建立该号的索引
multiKeyReset(int,int):根据传入的列号,建立两个列的索引
multiKeyReset(int,int,int):根据传入的列号,建立三个列的索引
dynamicKeyReset2(int[]):根据传入的列,建立多个列的索引
multiKeyFind(Object):根据设置的一个列的索引,查找满足的行,与multiKeyReset(int)相对应
multiKeyFind(Object,Object):根据设置的两个列的索引,查找满足的行,与multiKeyReset(int,int)相对应
multiKeyFind(Object,Object,Object):根据设置的三个列的索引,查找满足的行,与multiKeyReset(int,int,int)相对应
dynamicKeyFind2(Object[]):根据设置的多个列的索引,查找满足的行,与dynamicKeyReset2(int[])相对应
nextKeyList(): 根据索引找到了多行之后,可以依次取得下一行。
注意,当某个内存表采用共享内存方式存储时,如果子线程需要采用复制方式或者引用方式来访问这个共享内存时。子线程的内存表都是采用引用的方式来或者原先共享内存中的索引。
2.2. 内存表的主线程与子线程间共享
当主线程创建好一个内存表后,可以将其传给子线程进行访问。缺省情况下,为了线程安全,都是会复制一份新的内存表,传给子线程。但是如果希望节约内存开支,采用引用的方式来访问,就需要做一些特定的操作。
Sheet.setThreadType(int)可以指定当前内存表传给子线程时的共享方式。
其中getThreadType() == 1时,是直接传入引用,此时特别需要注意线程共享问题。不能对内存表进行逐行的读写操作。只能做批量添加等操作。除了以下设置成线程安全的方法可供访问,其他的方法都会存在线程安全问题:
initFromSheet:将{arg1}中的数据根据设定的列对应关系全部导入到表格中
appendFromSheet:将{arg1}中的数据根据设定的列对应关系,追加导入到表格中
loadFromSheet:将{arg1}中数据全部导入表格
loadFromList:将导出列表{arg1}的数据重新导入到表格中
loadFromExcelFile:从Excel中导入数据到内存表
appendFromResult:将查询结果({arg1})中的数据根据设定的列对应关系追加导入到表格中
loadFromResult:将查询结果({arg1})中的数据根据设定的列对应关系全部导入到表格中
loadFromResult:将查询结果({arg1})中的数据根据设定的列对应关系全部导入到表格中
loadFromView:将查询结果({arg1})中的数据全部导入表格
getThreadType() == 2:采用共享数据的方式访问。此时会有一个新的内存表,但是指向同一个数组。此时当进行读取时,是线程安全的。但是当需要写入数据时,是线程不安全的。
因此,getThreadType() == 2用于如果需要逐条读取的,只读不写;
否则使用getThreadType() == 1,只能通过批量导入写入数据。

猜你喜欢

转载自silencelight.iteye.com/blog/2294776