Hadoop自定义数据类型
程序员文章站
2022-06-07 18:41:20
...
Hadoop里面有一些内置的数据类型,例如:
数据类型 | Hadoop数据类型 |
整型 | IntWritable |
双字节数值 | DoubleWritable |
布尔型 | BooleanWritable |
长整型数 | LongWritable |
使用UTF8格式存储的文本 | Text |
浮点数 | Floatwritable |
但当我们在MapReduce上的键或者值需要存储两个或者以上的数据时,这些基础的数据类型就满足不了我们的需求,故我们可以通过自定义数据类型来储存我们的数据。
例子:自定义TestWritable数据类型,用来存储一个Double数据和一个String数据。
package type;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.Writable;
/*
*用来自定义数据类型,这里的接口为 Writable:为自定义值类型,到时定义完类型后,自定义类型名为此类名
*自定义类型步骤:(1)继承Writable接口,重写方法。
*(2)你的类型想设置多少个数据,就定义多少个全局变量
*(3)重写无参有参构造方法,写各个变量的set、get函数(右键Source->Generate Gets..里面)
* (4)按要求的格式写write、readFields方法
* (5)如果自定义格式要作为reducer输出的话,重写toString方法。
* 注意:write、readFields方法里的数据顺序要一致
*/
public class TestWritable implements Writable{
private double length;//存储一个Double数据
private String word;//存储一个String数据
//无参构造方法
public TestWritable() {
}
//有参构造方法
public TestWritable(double length, String word) {
super();
this.length = length;
this.word = word;
}
//write、readFields格式基本定死的,根据你自定义的值进行修改,
//注意两个方法里面的值的顺序要一样。我这里都是先写length再写word
@Override
public void write(DataOutput out) throws IOException {
// TODO Auto-generated method stub
out.writeDouble(length);
out.writeUTF(word);
}
@Override
public void readFields(DataInput in) throws IOException {
// TODO Auto-generated method stub
length = in.readInt();
word = in.readUTF();
}
//如果自定义数据类型要在最终输出的话就要设置这个,不然会输出值的路径
@Override
public String toString() {
// TODO Auto-generated method stub
return length + "," + word;
}
//定义数据的get、set方法,这样才能给自定义数据类型赋值。
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
}
定义好数据类型后就可以在主函数去引用这个数据类型了,我这里mapper和Reducer的值输出都用了自定义数据类型。
package type;
import java.io.IOException;
//记得导入hadoop里面的包,不然会报错java.io.IOException: Unable to initialize any output collector
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class TestDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException{
Configuration conf = new Configuration();
Job job = Job.getInstance(conf,"WordCount");
//重要:指定本job所在的jar包
job.setJarByClass(TestDriver.class);
//设置wordCount所用的mapper逻辑类为哪个类
job.setMapperClass(FlowerMapper.class);
//设置wordCount所用的reducer逻辑类为哪个类
job.setReducerClass(FlowerReducer.class);
//设置map阶段输出的kv(key,value)数据类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(TestWritable.class);//使用我们自定义的数据类型作为值输出
//设置最终输出的kv数据类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(TestWritable.class);
//设置输出格式,设置为自定义类FlowerOutputFormat
// job.setOutputFormatClass(FlowerOutputFormat.class);
FileSystem.get(conf).delete(new Path(args[1]),true);//如果输出路径已存在则删除
//设置要处理的文本数据所存放的路径
FileInputFormat.addInputPath(job,new Path(args[0])); //第一位输入的参数为输入的路径
// FileInputFormat.addInputPath(job,new Path(args[1]));
FileOutputFormat.setOutputPath(job, new Path(args[1])); //第二位输入的参数为输出的路径
System.exit(job.waitForCompletion(true)? 0:1); //输出任务是否执行成功
}
}
然后在MapReduce中要用自定义数据类型时,就要创建一个对象
TestWritable v=new TestWritable();
然后调用TestWritable里面的set方法往这个对象赋值。(在写TestWritable时写的get、set方法)
v.setLength(5.0);
v.setWord("sss");
调用TestWritable里面的get方法,获取这个对象的值
Double length=v.getLength();
String word=v.getWord;