从byte[]超大数组搜索指定某段子byte[]数组的问题

问题如题,byte[]超大数组包含若干个数据项,每个数据项开头4个字节是日期(yyyymmdd),我现在根据指定搜索条件(同样是yyyymmdd)去byte[]超大数组搜索有没有数据项开头4个字节是日期(yyyymmdd)值小于指定搜索条件值的,若成立,因为每个数据项byte[]长度固定,因此我就可解析出对应数据项数据,现在问题是,Arrays提供的二分查找需要使用前对数组排序,那样的话对我这个由特定顺序而又不能改变顺序的byte[]是不适合的,因此求一算法实现对我前述问题一种高速搜索算法
[b]问题补充:[/b]
由于具体协议决定了byte[]的byte顺序不能打乱,不然对整个数据含义就发生了变化,因此不能进行排序搜索,我们目前采用的方式如下:
[code="java"]
private byte[] queryForList(String cacheName, HkStocQuot obj, String type){
//获取缓存对象
Cache c = InfoCacheMS.getInstance().getCache(cacheName);
//获取大数组
byte[] quote = (byte[]) (c.get(type).getObjectValue());
//循环步长为44----每个数据项含44个byte
for (int j = 0; j < quote.length; j += 44) {
//ConversionUtil.byte2int()方法用于获取每个数据项前4个byte,这4个字节就是每个数据项携带的日期字段值;obj.getTradeDate()为客户端提交的交易时间查询条件
if (new BigDecimal(ConversionUtil.byte2int(quote,j) + "").compareTo(obj.getTradeDate()) < 0) {
//do something。。。
}
}
}
[/code]
但我感觉这个实现性能不是很高,因为现在是一个是适时性要求极高的系统,因此希望各位高手踊跃给出解决方案

lz给出的算法的主要性能问题在于对byte[]的全遍历
而在数据没有经过排序的情况下
不把整个byte[]全部遍历一边,是不可能得到所有满足条件的结果的
所以,在不对数据按照时间预先排序的情况下
效率没有多大改善的余地

不过有一个小问题
不需要在循环当中作ConversionUtil.byte2int处理
可以预先把客户端提交的交易时间查询条件用上述处理的逆处理转化为4个字节的条件
然后在循环的时候,直接将转换后的条件与4字节的日期值进行比较
这样,只要作一次转换就够了

在对经过顺序排序的数据进行查找的时候,一旦发现某个点的日期值小于条件值
那么它之前的所有数据的日期都是满足条件的,
所以二分查找法可以避免全遍历,从而实现高效查找

lz提到“由于具体协议决定了byte[]的byte顺序不能打乱,不然对整个数据含义就发生了变化”
我想这与排序并不矛盾
可以在数据项中额外添加若干字节的顺序值
这样一来,byte[]是按照时间再排序之后,
原本的顺序信息也不会损失

我数据结构学得不好,所以不清楚如何高速检索。
但如果不考虑性能的话,会比较简单,顺序检索就可以了。
从数组的头开始,依次提取每个数据项的日期段,与检索条件比较,找出匹配项。
因为你的数据项本来是乱序的,感觉直接顺序查找应该没什么问题,如果先排序的话,就又增加的一步排序的消耗,反而不好。除非你要对该数组检索好几遍,那样的话,最好是排一下。

如果应用场景在批处理之类情况下
可以考虑先将byte[]中的时间和数据项解析出来
插入到一个TreeMap中,
当时间与数据项是1:N的关系时,可以把时间作为key,数据项的ArrayList作为value
就是TreeMap<String 时间, ArrayList<String 数据项>>
之后,就可以通过TreeMap.headMap(搜索条件值)得到满足搜索条件值的视图
迭代这个试图就可以得到对应的数据项

示例代码如下
假定有byte[] dataArray,数据项长度为固定值n
[code="java"]
public List searchDataFromByteArray(byte[] dataArray, String condition)
{
TreeMap dataMap = new TreeMap(dataArray/(4+n));
for (int i = 0 ; i < dataArray.length ; i+=(4+n))
{
// TODO :从byte[]的下标i开始解析出时间字串
String dateStr = this.convertToDateStr(dataArray, i);
// TODO :从byte[]的下标i开始解析出数据项字串
String data = this.convertToData(dataArray, i);
if (dataMap.containsKey(dateStr)
){
List valueList = (List)dataMap.get(dateStr);
valueList.add(data);
continue;
}
List valueList = new ArrayList();
valueList.add(data);
dataMap.put(dateStr, valueList);
}

SortedMap headMap = dataMap.headMap(condition);
Collection dataListCollection = headMap.values();
if (dataListCollection == null || 
    dataListCollection.size == 0
){
    return Collections.EMPTY_LIST;
}
List result = new ArrayList();
for (Iterator iter = dataListCollection.iterator() ; iter.hasNext() ; )
{
    result.addAll((List)iter.next());
}
return result();

}
[/code]

以上的做法,本质上还是先排序然后再作二分查找
如果数据量在100万左右的话,处理时间应当在几分钟左右
时间主要是消耗在TreeMap的生成上。

如果对效率的要求更高的话
就只能在创建/存储dataArray的时候预先按照时间项进行排序

如果应用场景在实时查询的情况下
(例如byte[]数据是以BLOB的形式存储在DB中)
建议修改数据存储结构设计
因为这个存储结构实在是不适合查询应用