欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;