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);
}
}
}
AccumuloHiveRow--Hive源码读取第二篇
猜你喜欢
转载自blog.csdn.net/weixin_42474635/article/details/89450335
今日推荐
周排行