分享

Hadoop 自定义Writable NullpointerException

问题导读
1、在定义Hadoop的Writable时候,如何使用到数组?
2、如何不需要通过外部传入,从in中读取即可呢?
3、如何解决空指针的问题?






Hadoop环境:Hadoop2.4

在定义Hadoop的Writable时候,有时需要使用到数组,而不是简单的字符串或者单个的数值。比如下面的代码:
  1. package test;  
  2.   
  3. import java.io.DataInput;  
  4. import java.io.DataOutput;  
  5. import java.io.IOException;  
  6.   
  7. import org.apache.hadoop.io.WritableComparable;  
  8. import org.slf4j.Logger;  
  9. import org.slf4j.LoggerFactory;  
  10.   
  11. public class MyData implements WritableComparable<MyData>,Cloneable {  
  12.     private Logger log = LoggerFactory.getLogger(MyData.class);  
  13.   
  14.       
  15.     private float[] distance;  
  16.       
  17.     public MyData(){// 空指针异常  
  18.         set(new float[6]);  // 注释掉此行代码,在readFields会有空指针异常  
  19.     }  
  20.       
  21.   
  22.     public MyData(float[] distance) {  
  23.         set(distance);  
  24.     }  
  25.     public  void set(float[] distance) {  
  26.         this.distance=distance;  
  27.     }  
  28.       
  29.       
  30.     @Override  
  31.     public void readFields(DataInput arg0) throws IOException {  
  32.         for(int i=0;i<distance.length;i++){  
  33.             distance[i]=arg0.readFloat();  
  34.         }  
  35.     }  
  36.     @Override  
  37.     public void write(DataOutput arg0) throws IOException {  
  38.       
  39.         for(int i=0;i<distance.length;i++){  
  40.               
  41.             arg0.writeFloat(distance[i]);  
  42.         }  
  43.     }  
  44.     @Override  
  45.     public int compareTo(MyData o) {// 当前值小于o则返回负数  
  46.               
  47.         float[] oDistance =o.distance;  
  48.         int cmp=0;  
  49.         for(int i=0;i<oDistance.length;i++){  
  50.               
  51.             if(Math.abs(this.distance[i]-oDistance[i])<0.0000000001){  
  52.                 continue; // 比较下一个  
  53.             }  
  54.             if(this.distance[i]<oDistance[i]){  
  55.                 return -1;  
  56.             }else{  
  57.                 return 1;  
  58.             }  
  59.         }  
  60.          
  61.         return cmp;  
  62.     }  
  63.       
  64.       
  65.     @Override  
  66.     public int hashCode(){  
  67.         int hashCode =0;  
  68.         for(int i=0;i<distance.length;i++){  
  69.               
  70.             hashCode=+Float.floatToIntBits(distance[i]);  
  71.         }  
  72.         return hashCode;  
  73.     }  
  74.   
  75.   
  76.     public float[] getDistance() {  
  77.         return distance;  
  78.     }  
  79.   
  80.     public void setDistance(float[] distance) {  
  81.         this.distance = distance;  
  82.     }  
  83.       
  84. }
复制代码


可以看到其无参构造函数里面含有一个初始化的操作,这个初始化的操作限定了其矩阵distance的维度(代码中设置为6),但是一般这个值由外部设置才比较合适,但是在读取的时候,也就是readFields的时候是从这个无参构造函数进入的,这里没有办法设置参数,没有办法在外面初始化这个矩阵的大小,但是不设置又不行,有没有什么办法呢?在Mahout的一些代码中可以看到类似的代码,比如VectorWritable,从VectorWritable可以找到解决这个问题的答案。先看看vectorWritable的一段代码:
  1. @Override  
  2. public void readFields(DataInput in) throws IOException {  
  3.    int flags = in.readByte();  
  4.    int size = Varint.readUnsignedVarInt(in);  
  5.    readFields(in, (byte) flags, size);  
  6. }
复制代码


通过这段代码可以知道,不一定要通过外部传入,其实可以从in中读取即可。具体如何做呢?定义一个数组distance的大小变量,比如为num,然后把num在write中写入,然后在readFields中先读出,然后再初始化数组distance,这样就不会有刚才的问题了。具体代码如下:
  1. package test;  
  2.   
  3. import java.io.DataInput;  
  4. import java.io.DataOutput;  
  5. import java.io.IOException;  
  6.   
  7. import org.apache.hadoop.io.WritableComparable;  
  8. import org.slf4j.Logger;  
  9. import org.slf4j.LoggerFactory;  
  10.   
  11. public class MyData implements WritableComparable<MyData>,Cloneable {  
  12.     private Logger log = LoggerFactory.getLogger(MyData.class);  
  13.   
  14.       
  15.     private float[] distance;  
  16.     private int num;  
  17.     public MyData(){// 此处不再有空指针异常  
  18.     //  set(new float[6]);  // 注释掉此行代码,在readFields不会有空指针异常  
  19.     }  
  20.       
  21.     public MyData(float[] distance) {  
  22.         this.num=distance.length;  
  23.         set(distance);  
  24.     }  
  25.     public  void set(float[] distance) {  
  26.         this.distance=distance;  
  27.     }  
  28.       
  29.       
  30.     @Override  
  31.     public void readFields(DataInput arg0) throws IOException {  
  32.         num = arg0.readInt();  
  33.         distance = new float[num];  
  34.         for(int i=0;i<distance.length;i++){  
  35.             distance[i]=arg0.readFloat();  
  36.         }  
  37.     }  
  38.     @Override  
  39.     public void write(DataOutput arg0) throws IOException {  
  40.         arg0.writeInt(num);  
  41.         for(int i=0;i<distance.length;i++){  
  42.               
  43.             arg0.writeFloat(distance[i]);  
  44.         }  
  45.     }  
  46.     @Override  
  47.     public int compareTo(MyData o) {// 当前值小于o则返回负数  
  48.               
  49.         float[] oDistance =o.distance;  
  50.         int cmp=0;  
  51.         for(int i=0;i<oDistance.length;i++){  
  52.               
  53.             if(Math.abs(this.distance[i]-oDistance[i])<0.0000000001){  
  54.                 continue; // 比较下一个  
  55.             }  
  56.             if(this.distance[i]<oDistance[i]){  
  57.                 return -1;  
  58.             }else{  
  59.                 return 1;  
  60.             }  
  61.         }  
  62.          
  63.         return cmp;  
  64.     }  
  65.       
  66.       
  67.     @Override  
  68.     public int hashCode(){  
  69.         int hashCode =0;  
  70.         for(int i=0;i<distance.length;i++){  
  71.               
  72.             hashCode=+Float.floatToIntBits(distance[i]);  
  73.         }  
  74.         return hashCode;  
  75.     }  
  76.   
  77.   
  78.     public float[] getDistance() {  
  79.         return distance;  
  80.     }  
  81.   
  82.     public void setDistance(float[] distance) {  
  83.         this.distance = distance;  
  84.     }  
  85.       
  86. }
复制代码


通过上面的改进,就不用担心 空指针的问题了。







本文转载自:fansy1990

没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条