车牌模糊搜

车牌搜索的时候,经常碰到只有部分车牌好,而不是完整的,针对这正情况,为了提高查询速度,特提供此功能

 

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;
  }
 }
 

}

posted @ 2021-05-11 18:33  clima  阅读(306)  评论(1)    收藏  举报