AccumuloHiveRow--Hive源码读取第二篇

package org.apache.hadoop.hive.accumulo;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang.builder.HashCodeBuilder;   //产生HashCode
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;

import com.google.common.base.Preconditions;

哈希散列应该是在大数据里应用的比较多了吧,在解决数据倾斜的时候就经常用到,hbase里的rowID也会用到哈希等,
那到底什么是哈希呢?
就是把任意长度的输入,通过散列算法变换成固定长度的输出,该输出就是散列值。
关于散列的注意点:
1、如果散列表中存在和散列原始输入K相等的记录,那么K必定在f(K)的存储位置上
2、不同关键字经过散列算法变换后可能得到同一个散列地址,这种现象称为碰撞
3、如果两个Hash不同(同一Hash算法),那么两个Hash值对应的原始输入也必定不同
HashCode有什么用
回到最关键的问题,HashCode有什么用?不妨举个例子:
1、假设内存中有0 1 2 3 4 5 6 7 8这8个位置,如果我有个字段叫做ID,那么我要把这个字段存放在以上8个位置之一,如果不用HashCode而任意存放,那么当查找时就需要到8个位置中去挨个查找
2、使用HashCode则效率会快很多,把ID的HashCode%8,然后把ID存放在取得余数的那个位置,然后每次查找该类的时候都可以通过ID的HashCode%8求余数直接找到存放的位置了
3、如果ID的 HashCode%8算出来的位置上本身已经有数据了怎么办?这就取决于算法的实现了,比如ThreadLocal中的做法就是从算出来的位置向后查找第 一个为空的位置,放置数据;HashMap的做法就是通过链式结构连起来。反正,只要保证放的时候和取的时候的算法一致就行了。
4、如果ID的 HashCode%8相等怎么办(这种对应的是第三点说的链式结构的场景)?这时候就需要定义equals了。先通过HashCode%8来判断类在哪一 个位置,再通过equals来在这个位置上寻找需要的类。对比两个类的时候也差不多,先通过HashCode比较,假如HashCode相等再判断 equals。如果两个类的HashCode都不相同,那么这两个类必定是不同的。
public class AccumuloHiveRow implements Writable{

   private String rowId;
   private List<ColumnTuple> tuples=new ArrayList<ColumnTuple>();
   
   public AccumuloHiveRow(){}
   
   public AccumuloHiveRow(String rowId){
      this.rowId=rowId;
   }
   
   public void setRowId(string rowId){
      this.rowId=rowId;
   }
   
 
   public List<ColumnTuple> getTuples(){
      return Collections.unmodifiableList(tuples);
   }
   
   public List<ColumnTuple> getTuples(){
      return Collections.unmodifiableList(tuples);
   }
   
   /**
   * @return true if this instance has a tuple containing fam and qual, false otherwise.
   */
   public boolean hasFamAndQual(Text fam,Text qual){
      for(ColumnTuple tuple:tuples){
         if(tuple.getCf().equals(fam) && tple.getCq().equals(qual)){
            return true;
         }
      }
      return false;
   }
   
   /**
   * @return byte [] value for first tuple containing fam and qual or null if no match.
   */
   public byte[] getValue(Text fam,Text qual){
      for(ColumnTuple tuple:tuples){
         if(tuple.getCf().equals(fam) && tuple.getCq().equals(qual)){
           return tuple.getValue();
         }         
      }
      return null;
   }
   
   public String getRowId(){
     return rowId;
   }
   
   public void clear(){
     this.rowId=null;
     this.tuples=new ArrayList<ColunTuple>();
   }
   
   @Override
   public string toString(){
     StringBuilder builder=new StringBuilder("AccumuloHiveRow{");
     builder.append("rowId'").append(rowId).append("',tuples:");
     for(ColumnTuple tuple:tuples){
       builder.append(tuple.toString());
       builder.append("\n");
     }
     return builder.toString();
   }
   
   @Override
   public boolean equals(Object o){
     if(o instanceof AccumuloHiveRow){
       AccumuloHIveRow other=(AccumuloHiveRow) o;
       if (null==rowId){
         if(null!=other.rowId){
           return false;
         }        
       }else if(!rowId.equals(other.rowId)){
         return false;
       }
     
       return tuples.equals(other.tuples);
     }
   
     return false;
   }
   
   @Override
   public void write(DataOutput dataOutput) throws IOException {
     if(null !=rowId){
       dataOutput.writeBoolean(true);
       dataOutput.writeUTF(rowId);
     }else{
       dataOutput.writeBoolean(false);
     }
     int size=tuples.size();
     dataOutput.writeInt(size);
     for(ColumnTuple tuple:tuples){
       Text cf=tuple.getCf(), cq=tuple.getCq();
       dataOutput.writeInt(cf.getLength());
       dataOutput.write(cf.getBytes(),0,cf.getLength());
       dataOutput.writeInt(cq.getLength());
       dataOutput.write(cq.getLength());
       dataOutput.write(cq.getBytes(),0,cq.getLength());
       byte[] value=tuple.getValue();
       dataOutput.writeInt(vale.length);
       dataOutput.write(value);
     }
   }
   
   @Override
   public void readFields(DataInput dataInput) throws IOException{
     if(dataInput.readBoolean()){
        rowId=dataInput.readUTF();
     }
     int size=dataInput.readInt();
     for(int i=0;i<size;i++){
       int cfLength=dataInput.readInt();
       byte[] cfData=new byte[cfLength];
       dataInput.readFully(cfData,0,cfLength);
       Text cf=new Text(cfData);
       int cqLength=dataInput.readInt();
       byte[] caData=new byte[cqLength];
       dataInput.readFully(caData,0,cqLength);
       Text cq=new Text(cqData);
       int valSize=dataInput.readInt();
       byte[] val=new byte[valSize];
       for(int j=0;j<valSize;j++){
         val[j]=dataInput.readByte();
       }
       tuples.add(new ColumnTuple(cf,ca,val));
     }
   }
   
   public void add(String cf,String qual,byte[] val){
     Preconditions.checkNotNull(cf);
     Preconditions.checkNotNull(qual);
     Precoditions.checkNotNull(val);
     
     add(new Text(cf), new Text(qual), val);
   }
   
   public void add(Text cf,Text qual,byte[] val){
     Precoditions.checkNotNull(cf);
     Precoditions.chekNotNull(qual);
     Precoditions.checkNotNull(val);
     
     tuples.add(new ColumnTuple(cf,qual,val));
   }
   
   public static class ColumnTuple{
     private final Text cf;
     private final Text cq;
     private final byte[] value;
     
     public ColumnTuple(Text cf,Text cq,byte[] value){
       this.value=value;
       this.cf=cf;
       this.cq=cq;
     }
     public byte[] getValue(){
       return value;
     }
     
     public Text getCf(){
       return cf;
     }
     
     public Text getCq(){
       return cq;
     }
     
     @Override
     public boolean equals(Object o){
       if(o instanceof ColumnTuple){
         ColunTuple other=(ColumnTuple) o;
         if(null==cf){
           if(null!=other.cf){
             return false;
           }
         }else if(!cf.equals(other.cf)){
           return false;
         }
       }
       
       if(null==cq){
         if(null!=other.cq){
           return false;
         }
       }else if(!cq.equals(other.cq)){
         return false;
       }
       
       if(null==value){
         if(null!=other.value){
           return false;
         }
       }
       
       return Arrays.equals(value,other.value);
     }
     return false;
   }
   @Override
   public String toString(){
     return cf+" "+cq+" "+new String(value);
   }
  }
}

猜你喜欢

转载自blog.csdn.net/weixin_42474635/article/details/89450335
今日推荐