✌✌✌古代人は言いたいことがあります。良い記憶は悪いペンほど良くはありません。千マイルの旅は1つのステップから始まります。毎日1000行のコードが不可欠です。毎日要約を書いてください。大きな工場。希望に満ちていれば無敵になります、ははは!!!✌✌✌
1.✌質問の要件
レコードテーブル:
ID | 市区町村番号 | エアインデックス |
---|---|---|
001 | 03 | 245 |
002 | 02 | 655 |
003 | 05 | 743 |
004 | 04 | 246 |
005 | 02 | 956 |
006 | 01 | 637 |
007 | 05 | 831 |
008 | 03 | 683 |
009 | 02 | 349 |
シティテーブル:
市区町村番号 | 都市名 |
---|---|
01 | 長沙 |
02 | 株洲 |
03 | 湘潭 |
04 | 懐化 |
05 | 岳陽 |
ターゲットテーブル:
ID | 都市名 | エアインデックス |
---|---|---|
001 | 湘潭 | 245 |
002 | 株洲 | 655 |
003 | 岳陽 | 743 |
004 | 懐化 | 246 |
005 | 株洲 | 956 |
006 | 長沙 | 637 |
007 | 岳陽 | 831 |
008 | 湘潭 | 683 |
009 | 株洲 | 349 |
2.✌アイデアを実現する
繰り返されるフィールドをマップのキーとして使用し、他の属性はBeanに値としてカプセル化されます。
マップを通過した後のファイルの形式は次のとおりです。
市区町村番号 | ID | 都市名 | エアインデックス | ファイルの種類 |
---|---|---|---|---|
1 | 006 | 637 | 記録 | |
1 | 長沙 | 市 | ||
2 | 002 | 655 | 記録 | |
2 | 005 | 956 | 記録 | |
2 | 009 | 349 | 記録 | |
2 | 株洲 | 市 | ||
3 | 001 | 245 | 記録 | |
3 | 008 | 683 | 記録 | |
3 | 湘潭 | 市 | ||
4 | 004 | 246 | 記録 | |
4 | 懐化 | 市 | ||
5 | 003 | 743 | 記録 | |
5 | 007 | 831 | 記録 | |
5 | 岳陽 | 市 |
1.すべてのプロパティをオブジェクトにカプセル化し、同時にシリアル化を実現し
ます。2。Mapの入力形式はLongWritable、Textである必要があります。3。Map
の出力形式はText、Beanである必要があります。4。Reduce
の出力形式はBeanである必要があります。 、NullWritable
3、✌コードの実装
1.✌Beanクラス
import org.apache.hadoop.io.Writable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class Bean implements Writable {
//定义属性
private String id;
private String pid;
private int amount;
private String pname;
private String type;
//定义空参构造,为后面反射使用
public Bean() {
super();
}
//有参构造
public Bean(String id, String pid, int amount, String pname, String type) {
this.id = id;
this.pid = pid;
this.amount = amount;
this.pname = pname;
this.type = type;
}
//重写toString方法
@Override
public String toString() {
return id + "\t" + pname + "\t\t" + amount;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
//重写序列化方法
@Override
public void write(DataOutput out) throws IOException {
out.writeUTF(id);
out.writeUTF(pid);
out.writeInt(amount);
out.writeUTF(pname);
out.writeUTF(type);
}
//反序列化方法
@Override
public void readFields(DataInput in) throws IOException {
id = in.readUTF();
pid = in.readUTF();
amount = in.readInt();
pname = in.readUTF();
type = in.readUTF();
}
}
2.✌マップクラス
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import java.io.IOException;
public class Map extends Mapper<LongWritable, Text, Text, Bean> {
String fileName;
//获得文件的名称,因为在同一目录,方便再map阶段对不同表做不同操作
@Override
protected void setup(Context context) throws IOException, InterruptedException {
FileSplit split = (FileSplit) context.getInputSplit();
fileName = split.getPath().getName();
}
//map阶段,将文章内容封装为Bean对象
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
if (fileName.startsWith("record")) {
String[] words = line.split("\t");
context.write(new Text(words[1]), new Bean(words[0], words[1], Integer.parseInt(words[2]), "", "record"));
} else {
String[] words = line.split("\t");
context.write(new Text(words[0]), new Bean("", words[0], 0, words[1], "city"));
}
}
}
3.✌クラスを減らす
import org.apache.commons.beanutils.BeanUtils;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
public class Reduce extends Reducer<Text, Bean, Bean, NullWritable> {
@Override
protected void reduce(Text key, Iterable<Bean> values, Context context) throws IOException, InterruptedException {
//存取多个Bean对象
ArrayList<Bean> list = new ArrayList<>();
Bean pd = new Bean();
//对不同表做不同操作,设置pname
for (Bean value : values) {
if ("record".equals(value.getType())) {
Bean temp = new Bean();
try {
BeanUtils.copyProperties(temp, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
list.add(temp);
} else {
try {
BeanUtils.copyProperties(pd, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
for (Bean bean : list) {
bean.setPname(pd.getPname());
context.write(bean, NullWritable.get());
}
}
}
4.✌ドライバークラス
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
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;
import org.apache.log4j.BasicConfigurator;
import java.io.IOException;
public class Driver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//设置本地输入输出路径
args = new String[]{
"D:/input", "D:/output"};
BasicConfigurator.configure();
//配置信息
Configuration conf = new Configuration();
//获取job对象
Job job = Job.getInstance(conf);
//关联相关类
job.setJarByClass(Driver.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);
//设置map输出类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Bean.class);
//设置最终输出类型
job.setOutputKeyClass(Bean.class);
job.setOutputValueClass(NullWritable.class);
//设置文件路径
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//提交任务
boolean result = job.waitForCompletion(true);
System.exit(result ? 0 : 1);
}
}
、