车牌模糊搜
车牌搜索的时候,经常碰到只有部分车牌好,而不是完整的,针对这正情况,为了提高查询速度,特提供此功能
public class PlateServiceImpl extends PlateUtils{
private Array array=new Array();
private int minCharaterCount=3;
public PlateServiceImpl(){
Circle value=new Circle(1,0x7fffffffffffffffL);
array.add(0, value);
}
//添加车牌到库中
public boolean add(String plate){
long pl=PlateUtils.encode(plate);
if(pl>0){
add(plate);
return true;
}
return false;
}
//同上,变成了整形车牌
public boolean add(long plate){
if(plate>0){
int length=PlateUtils.MAX_PLATE_NUMBER_SIZE-minCharaterCount;
//检查车牌长度,判断是否8位车牌
if((plate&0x3f90)==0){
length--;
}
add0(plate);
for(byte i=1;i<=length;i++){
//拼接车牌号、车牌颜色、移位数
add0(adjust(plate,i));
}
return true;
}
return false;
}
private void add0(long plate){
int startIndex=0,endIndex=array.size()-1,middIndex;
while(startIndex<=endIndex){
middIndex=((startIndex+endIndex)>>1);
Circle v=array.get(middIndex);
if(plate>v.getEndKey()){
startIndex=middIndex+1;
}
else if(plate<v.getStartKey()){
endIndex=middIndex-1;
}
else{
if(v.isFull()){//当前分段数据放满,拆分当前分段为两个
Circle tmp=v.split();
this.array.add(middIndex+1, tmp);
if(plate>=tmp.getStartKey()){//判断放入源段,还是新扩充段
v=tmp;
}
}
v.add(plate);
break;
}
}
}
//查询车牌是否存在
public boolean find(String plate){
if(plate!=null){
long pl=PlateUtils.encode(plate);
if(pl>0){
return find(pl);
}
}
return false;
}
//同上,参数为整形车牌
public boolean find(long plate){
if(plate>0){
//车牌变换
int startIndex=0,endIndex=array.size()-1,middIndex;
while(startIndex<=endIndex){
middIndex=((startIndex+endIndex)>>1);
Circle v=array.get(middIndex);
if(plate>v.getEndKey()){
startIndex=middIndex+1;
}
else if(plate<v.getStartKey()){
endIndex=middIndex-1;
}
else{
return v.find(plate);
}
}
}
return false;
}
//搜索车牌,part车牌号码片段,size返回数据的最大值限制
public List<Long> search(String part,int size){
if(part!=null&&part.length()>=minCharaterCount){
long pl=PlateUtils.encode2(part);
if(pl>0){
return search(pl,size);
}
}
return null;
}
//同上
public List<Long> search(long part,int size){
List<Long> list=new ArrayList<Long>();
if(part>0){
int length=PlateUtils.length(part);
if(length>=minCharaterCount){
long min=part;
long max=min|LOW_MASK_TABLE[length]|0x7f;
int startIndex=0,endIndex=array.size()-1,middIndex;
while(startIndex<=endIndex){
middIndex=((startIndex+endIndex)>>1);
Circle v=array.get(middIndex);
if(min>v.getEndKey()){
startIndex=middIndex+1;
}
else if(min<v.getStartKey()){
endIndex=middIndex-1;
}
else{
middIndex++;
//发现第一个符合要求的段
int count=v.search(min,max,size,list);
//向下继续找其他段
while(count>0&&middIndex<array.size()&list.size()<size){
v=array.get(middIndex++);
if(v.getStartKey()>max){
break;
}
count=v.search(v.getStartKey(),max,size,list);
}
break;
}
}
}
for(int i=0;i<list.size();i++){
list.set(i, restore(list.get(i)));
}
}
return list;
}
public int size(){
return this.array.size();
}
/**
* 分布式HASH,本类对应HASH环中的一个段
* startKey 段的起始值
* endKey 段的结束值
* value 本段存放数据
*/
private static class Circle{
private static final int BLOCK_SIZE=2048;
private int length;
private long startKey;
private long endKey;
private long[] value;
public Circle(long startKey,long endKey){
this.startKey=startKey;
this.endKey=endKey;
this.value=new long[BLOCK_SIZE];
this.length=0;
}
public long getStartKey() {
return startKey;
}
public long getEndKey() {
return endKey;
}
//二分法插入
public void add(long plate){
int startIndex=0,endIndex=this.length-1,middIndex;
while(startIndex<=endIndex){
middIndex=((startIndex+endIndex)>>1);
if(plate>value[middIndex]){
startIndex=middIndex+1;
}
else{
endIndex=middIndex-1;
}
}
for(int i=length-1;i>=startIndex;i--){
this.value[i+1]=this.value[i];
}
this.value[startIndex]=plate;
this.length++;
}
//二分法查找
public boolean find(long plate){
int startIndex=0,endIndex=this.length-1,middIndex;
while(startIndex<=endIndex){
middIndex=((startIndex+endIndex)>>1);
if(plate>this.value[middIndex]){
startIndex=middIndex+1;
}
else if(plate<this.value[middIndex]){
endIndex=middIndex-1;
}
else{
return true;
}
}
return false;
}
/**
* 查询在 min(包含)和max(不包含)之间得数
* @param min 最小值(包含)
* @param max 最大值(不包含)
* @param size 查询符合条件数据的最大值
* @param list 符合条件数的存放处
*/
public int search(long min,long max,int size,List<Long> list){
int startIndex=0,endIndex=this.length-1,middIndex, count=0;
while(startIndex<=endIndex){
middIndex=((startIndex+endIndex)>>1);
if(min>this.value[middIndex]){
startIndex=middIndex+1;
}
else if(min<this.value[middIndex]){
endIndex=middIndex-1;
}
else{
break;
}
}
for(int i=startIndex;i<this.length&list.size()<size;i++){
long tmp=this.value[i];
if(tmp>=min&tmp<max){
list.add(tmp);
count++;
}
else{
break;
}
}
return count;
}
public int size(){
return this.length;
}
public boolean isFull(){
return this.length==this.value.length;
}
//HASH端数据太多,存贮空间用尽,重新开辟一个新的空间,并将数据的一半迁移至新空间
public Circle split(){
int pos=(this.length>>1);
long data=this.value[pos];
Circle v=new Circle(data,endKey);
System.arraycopy(this.value, pos, v.value, 0, pos);
v.length=pos;
this.endKey=data-1;
this.length=pos;
return v;
}
}
/**
* 数组,和List功能完全一样
*
*/
private static class Array{
private static final int ADD_SIZE=8192;
private int length;
private Circle [] data;
public Array(){
this.data=new Circle[ADD_SIZE];
this.length=0;
}
public void add(int index,Circle t){
if(this.length==this.data.length){
Circle[] tmp=this.data;
this.data=new Circle[this.length+ADD_SIZE];
System.arraycopy(tmp, 0, this.data, 0, this.length);
}
for(int i=length-1;i>=index;i--){
this.data[i+1]=this.data[i];
}
this.data[index]=t;
length++;
}
public Circle get(int index){
if(index<this.length){
return data[index];
}
return null;
}
public int size(){
return this.length;
}
}
}