Hadoop 高级程序设计(一)---复合键 自定义输入类型

简介:

在大数据处理的基本方法上,对于相互间计算的依赖性不大的数据,mapreduce采用分治的策略进行处理,将大的问题划分成小的问题进行求解,使得问题变得简单可行,同时在处理问题上面,MapReduce框架隐藏了很多的处理细节,将数据切分,任务调度,数据通信,容错,负载均衡.....交给了系统负责,对于很多问题,只需要采取框架的缺省值完成即可,用户只需完成设计map函数很reduce函数即可。

复合键

在一般的情况下只需要使用简单的<key,value>对即可,但是在一些复杂的情况下可以完成很多有效的处理,可以减少网络数据通信开销,提高程序计算效率。

例子:倒排索引 文档检索系统中最常用的数据结构,广泛的应用与全文检索,存储某个单词或者词组在一个文挡或是多个文档中的存储位置的映射,根据内容来查找文档的方式。由于不是根据文档查找内容 而是根据内容来查找文档,进行相反的操作,继而成为倒排索引。

代码:

package reverseIndex;

import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileSplit;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;

/**
 * 倒排索引:根据内容查找文件
 * xd is a good man ->file1.txt
 * good boy is xd   ->file2.txt
 * xd like beautiful women ->file3.txt
 * 对应下:
 * xd ->file1.txt file2.txt file3.txt
 * is ->file1.txt file2.txt
 * a ->file1.txt
 * good ->file1.txt file2.txt
 * man ->file1.txt
 * boy ->file2.txt
 * like ->file3.txt
 * beautiful ->file3.txt
 * women ->file3.txt
 * 在每个map函数中 所需数据对 是<"单词+文件名","词频"> 便于combiner的词频统计
 * 而在combiner中  将数据对变为<"单词","文件名+词频"> 便于将相同的key的数据 分发到 同一个reducer中执行 (HashPartition).
 * @author XD
 */
public class inverseIndex {
	public static class Map extends Mapper<LongWritable,Text,Text,Text>{
		private Text keyInfo = new Text();	//key值
		private Text valueInfo = new Text();	//value值
		private FileSplit split;	//回去文件的splie对象
		public void map(LongWritable key,Text value,Context context) throws IOException, InterruptedException{
			split = (FileSplit)context.getInputSplit();	//关键 获取<key,value>所属的split对象
			StringTokenizer itr = new StringTokenizer(value.toString());
			while(itr.hasMoreTokens()){
				int splitIndex = split.getPath().toString().indexOf("file");//获取文件名 包含file的索引位置
				keyInfo.set(itr.nextToken()+":"+split.getPath().toString().substring(splitIndex));	//设定key值
				valueInfo.set("1");
				context.write(keyInfo, valueInfo);
			}
		}
	}
	public static class combiner extends Reducer<Text,Text,Text,Text>{
		private Text info = new Text();	//为了拆分 key值 准备存储新的value值
		public void reduce(Text key,Iterable<Text>values,Context context) throws IOException, InterruptedException{
			int sum = 0;
			for(Text val:values){
				sum += Integer.parseInt(val.toString());
			}
			int splitIndex = key.toString().indexOf(":");
			info.set(key.toString().substring(splitIndex+1)+":"+sum);	//新的value值
			key.set(key.toString().substring(0, splitIndex));
			context.write(key, info);
		}
	}
	public static class Reduce extends Reducer<Text,Text,Text,Text>{
		private Text result = new Text();	//设定最终的输出结果
		public void reduce(Text key,Iterable<Text>values,Context context) throws IOException, InterruptedException{
			String list = new String();
			for(Text val:values){
				list += val.toString()+";";	//不同的索引文件分隔开来
			}
			result.set(list);
			context.write(key,result);
		}
	}
}

用户自定义数据类型

Hadoop中提供了很多的内置数据类型,但是在解决一些复杂的问题,这些内置的简单数据类型很难满足用户的需求,需要自定义数据类型。用户在自定义数据类型的时候,需要实现Writable接口,以便数据可以被序列化后完成网络传输或是文件的输入输出。此外,要是数据需要作为主键使用或者需要比较数值大小时,需要实现WritableComparable接口。

例子:

package com.rpc.nefu;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.WritableComparable;

//对自己输入的数据需要 可序列化  即自定义一个可序列化的类
public class keyvalue implements WritableComparable<keyvalue>{
	public int x,y;
	public keyvalue(){
		this.x = 0;
		this.y = 0;
	}
	public keyvalue(int x1,int y1){
		this.x = x1;
		this.y = y1;
	}
	@Override
	public void readFields(DataInput in) throws IOException {
		// TODO Auto-generated method stub
		x = in.readInt();
		y = in.readInt();

	}

	@Override
	public void write(DataOutput out) throws IOException {
		// TODO Auto-generated method stub
		out.writeInt(x);
		out.writeInt(y);
	}
	public int distanceFromOrigin(){
		return (x*x+y*y);
	}
	public boolean equals(keyvalue o){
		if(!(o instanceof keyvalue)){
			return false;
		}
		return (this.x == o.x) && (this.y == o.y);
	}
	public int hashCode() {
		return Float.floatToIntBits(x)
			^ Float.floatToIntBits(y);

	}
	public String toString(){
		return Integer.toString(x)+","+Integer.toString(y);
	}
	@Override
	public int compareTo(keyvalue o) {
		//return x;
		// TODO Auto-generated method stub
		if(x > o.x){
			return 1;
		}else if(x == o.x){
			return 0;
		}else{
			return -1;
		}
	}
}

时间: 2024-10-09 12:45:10

Hadoop 高级程序设计(一)---复合键 自定义输入类型的相关文章

Hadoop 高级程序设计(二)---自定义输入输出格式

Hadoop提供了较为丰富的数据输入输出格式,可以满足很多的设计实现,但是在某些时候需要自定义输入输出格式. 数据的输入格式用于描述MapReduce作业的数据输入规范,MapReduce框架依靠数据输入格式完后输入规范检查(比如输入文件目录的检查),对数据文件进行输入分块(InputSpilt)以及提供从输入分快中将数据逐行的读出,并转换为Map过程的输入键值对等功能.Hadoop提供了很多的输入格式,TextInputFormat和KeyValueInputFormat,对于每个输入格式都有

Hadoop 高级程序设计(三)---自定义Partition和Combiner

Hadoop提供了缺省的Partition来完成map的输出向reduce分发处理.有时也需要自定义partition来将相同key值的数据分发到同一个reduce处理,为了减少map过程输出的中间结果键值对的数量,降低网络数据通信开销,用户也可以自定制combiner过程. 自定制Partition过程: 在mapreduce中,partition用于决定Map节点输出将被分到哪个Reduce节点,MapReduce提供的缺省Partition是HashPartition,他根据每条数据的主键

《JAVASCRIPT高级程序设计》事件处理程序和事件类型

一.事件流 谈到事件,首要要理解事件流的概念:事件流是指从页面接受事件的顺序:“DOM2级事件”规定事件流包括三个阶段:事件捕获阶段.处于目标阶段和事件冒泡阶段.目前大部分的浏览器的事件流是事件冒泡,即最开始由具体的元素接收事件,然后逐级传播到不具体的节点,直到传播到windows对象:另一种事件流是事件捕获,目前使用得比较少,是指文档对象先接收到事件,然后逐级向下,一直传播到事件的实际目标. 二.事件处理程序 1.两种表示方式 <input type="button" valu

《JavaScript高级程序设计》第5章 Object类型---Array---学习心得

1.创建数组的方法: 使用Array构造函数: var colors=new Array() var colors=new Array(20)//l创建一个包含20项的数组 var colors=new Array("red","blue","green")//创建一个包含3个字符串的数组 2. 使用数组字面量表示: var colors=["red","blue","green"]//

干货--Hadoop自定义数据类型和自定义输入输出格式整合项目案例

正文开始前 ,先介绍几个概念 序列化 所谓序列化,是指将结构化对象转化为字节流,以便在网络上传输或写到磁盘进行永久存储. 反序列化 是指将字节流转回到结构化对象的逆过程 序列化在分布式数据处理的两个大领域经常出现:进程间通信和永久存储 在Hadoop中,系统中多个节点上进程间的通信是通过"远程过程调用"(remote procedure call,RPC)实现的 .RPC协议将消息序列化成二进制流后发送到远程节点,远程节点接着将二进制流反序列化为原始消息 Hadoop使用了自己写的序列

hadoop复合键排序使用方法

在hadoop中处理复杂业务时,需要用到复合键,复合不同于单纯的继承Writable接口,而是继承了WritableComparable<T>接口,而实际上,WritableComparable<T>接口继承了Writable和Comparable<T>接口,如果只需要使用某一个类作为传值对象而不是作为key,继承Writable接口即可. 上源码: public interface WritableComparable<T> extends Writabl

hadoop编程小技巧(5)---自定义输入文件格式类InputFormat

Hadoop代码测试环境:Hadoop2.4 应用:在对数据需要进行一定条件的过滤和简单处理的时候可以使用自定义输入文件格式类. Hadoop内置的输入文件格式类有: 1)FileInputFormat<K,V>这个是基本的父类,我们自定义就直接使用它作为父类: 2)TextInputFormat<LongWritable,Text>这个是默认的数据格式类,我们一般编程,如果没有特别指定的话,一般都使用的是这个:key代表当前行数据距离文件开始的距离,value代码当前行字符串:

hadoop自定义输入格式

一个任务的开始阶段是由InputFormat来决定的! 1.在MapReduce框架中,InputFormat扮演的角色:– 将输入数据切分成逻辑的分片(Split),一个分片将被分配给一个单独的Mapper– 提供RecordReader的对象,该对象会从分片中读出<Key-Value>对供Mapper处理 1.1InputFormat对Mapper的影响:– 决定了Mapper的数量– 决定了Mapper的map函数接收的Key和Value 1.2InputFormat: InputFor

javascript高级程序设计 第十三章--事件

javascript高级程序设计 第十三章--事件js与HTML的交互就是通过事件实现的,事件就是文档或浏览器窗口中发生的一些特定的交互瞬间. 事件流:事件流描述的是从页面中接收事件的顺序,IE的是事件冒泡流,Netscape的是事件捕获流,这个两个是完全相反的事件流概念. 事件冒泡:由最具体的元素接收,然后逐级向上传播到更高级的节点,即事件沿DOM树向上传播,直到document对象. 事件捕获:不大具体的节点应该更早接收到事件,相当于沿DOM节点树向下级传播直到事件的实际目标,在浏览器中,是