Hadoop 自定义Writable NullpointerException,hadoopwritable
Hadoop 自定义Writable NullpointerException,hadoopwritable
Hadoop环境:Hadoop2.4
在定义Hadoop的Writable时候,有时需要使用到数组,而不是简单的字符串或者单个的数值。比如下面的代码:
package test; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import org.apache.hadoop.io.WritableComparable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyData implements WritableComparable<MyData>,Cloneable { private Logger log = LoggerFactory.getLogger(MyData.class); private float[] distance; public MyData(){// 空指针异常 set(new float[6]); // 注释掉此行代码,在readFields会有空指针异常 } public MyData(float[] distance) { set(distance); } public void set(float[] distance) { this.distance=distance; } @Override public void readFields(DataInput arg0) throws IOException { for(int i=0;i<distance.length;i++){ distance[i]=arg0.readFloat(); } } @Override public void write(DataOutput arg0) throws IOException { for(int i=0;i<distance.length;i++){ arg0.writeFloat(distance[i]); } } @Override public int compareTo(MyData o) {// 当前值小于o则返回负数 float[] oDistance =o.distance; int cmp=0; for(int i=0;i<oDistance.length;i++){ if(Math.abs(this.distance[i]-oDistance[i])<0.0000000001){ continue; // 比较下一个 } if(this.distance[i]<oDistance[i]){ return -1; }else{ return 1; } } return cmp; } @Override public int hashCode(){ int hashCode =0; for(int i=0;i<distance.length;i++){ hashCode=+Float.floatToIntBits(distance[i]); } return hashCode; } public float[] getDistance() { return distance; } public void setDistance(float[] distance) { this.distance = distance; } }可以看到其无参构造函数里面含有一个初始化的操作,这个初始化的操作限定了其矩阵distance的维度(代码中设置为6),但是一般这个值由外部设置才比较合适,但是在读取的时候,也就是readFields的时候是从这个无参构造函数进入的,这里没有办法设置参数,没有办法在外面初始化这个矩阵的大小,但是不设置又不行,有没有什么办法呢?在Mahout的一些代码中可以看到类似的代码,比如VectorWritable,从VectorWritable可以找到解决这个问题的答案。先看看vectorWritable的一段代码:
@Override public void readFields(DataInput in) throws IOException { int flags = in.readByte(); int size = Varint.readUnsignedVarInt(in); readFields(in, (byte) flags, size); }
package test; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import org.apache.hadoop.io.WritableComparable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyData implements WritableComparable<MyData>,Cloneable { private Logger log = LoggerFactory.getLogger(MyData.class); private float[] distance; private int num; public MyData(){// 此处不再有空指针异常 // set(new float[6]); // 注释掉此行代码,在readFields不会有空指针异常 } public MyData(float[] distance) { this.num=distance.length; set(distance); } public void set(float[] distance) { this.distance=distance; } @Override public void readFields(DataInput arg0) throws IOException { num = arg0.readInt(); distance = new float[num]; for(int i=0;i<distance.length;i++){ distance[i]=arg0.readFloat(); } } @Override public void write(DataOutput arg0) throws IOException { arg0.writeInt(num); for(int i=0;i<distance.length;i++){ arg0.writeFloat(distance[i]); } } @Override public int compareTo(MyData o) {// 当前值小于o则返回负数 float[] oDistance =o.distance; int cmp=0; for(int i=0;i<oDistance.length;i++){ if(Math.abs(this.distance[i]-oDistance[i])<0.0000000001){ continue; // 比较下一个 } if(this.distance[i]<oDistance[i]){ return -1; }else{ return 1; } } return cmp; } @Override public int hashCode(){ int hashCode =0; for(int i=0;i<distance.length;i++){ hashCode=+Float.floatToIntBits(distance[i]); } return hashCode; } public float[] getDistance() { return distance; } public void setDistance(float[] distance) { this.distance = distance; } }
通过上面的改进,就不用担心 空指针的问题了。
分享,成长,快乐
转载请注明blog地址:http://blog.csdn.net/fansy1990
在for 循环前面加上 pieces = new Piece[width][height]
报空指针应该是因为你没有告诉系统你要申请多大空间的数据,系统就没给你分配空间,没分配空间就找不到,找不到就空指针了。
你的数组元素没有初始化。在byTwo[i].aaa =i;前面加上byTwo[i]=new My();并且用大括号括起来,
在byOne[i].aaa =i;前面加上byOne[i]=new My();并且用大括号括起来,就行了。
完整的程序如下:
package myInstance;
import java.lang.reflect.Array;
public class ArrayUtils {
public static <T> T[] newArrayByArrayClass(Class<T[]> clazz, int length) {
return (T[]) Array.newInstance(clazz.getComponentType(), length);
}
public static <T> T[] newArrayByClass(Class<T> clazz, int length) {
return (T[]) Array.newInstance(clazz, length);
}
public static void main(String[] args) {
My[] byTwo = null;
byTwo = newArrayByClass(My.class, 10);//第一种方法
for(int i = 0;i < 10; i ++){
byTwo[i]=new My();
byTwo[i].aaa =i;
}
My[] byOne =null;
byOne = newArrayByArrayClass(My[].class, 10);//第二种方法
for(int i = 0;i < 10; i ++){
byOne[i]=new My();
byOne[i].aaa =i;
}
}
}
//定义“My”类
package myInstance;
public class My
{
public int aaa;
public My(){}
}
评论暂时关闭