关于mapreduce,再reduce方法中使用两次foreach来遍历values

星夜丶晚晚 2019-03-13 10:55:17
想用mapreduce找出几天中,每一天的气温最高的记录;代码思路很简单,日期作为key,时间和温度作为value。然后在reduce方法中对values先遍历一遍找到最高温度max,再遍历一遍values,找到最高温度的记录,但是很可惜,程序能输出,但是输出文件没有内容,不知是何缘由。个人怀疑是不是不能使用两次遍历。
输入文件中的格式是: 日期 时间 温度
例:
2017-06-23 08 12
2017-06-23 12 25
代码如下:
import java.io.IOException;
import java.net.URI;

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.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class MaxTemperature {
public static class MaxTemperatureMap extends Mapper<Object, Text, Text, Text>
{
@Override
public void map(Object key,Text value,Context context) throws IOException,InterruptedException
{
String[] str = value.toString().split(" ");
context.write(new Text(str[0]), new Text(str[1]+str[2]));
}
}

public static class MaxTemperatureReduce extends Reducer<Text, Text, Text, Text>
{

@Override
public void reduce(Text key ,Iterable<Text> values ,Context context) throws IOException,InterruptedException
{
//先找到最高温度max
int max=Integer.MIN_VALUE;
for(Text value:values) {
max=Math.max(max, Integer.parseInt(value.toString().substring(2)));

}
// context.write(key, new Text(String.valueOf(max)));
//再找到取到最高温度max时的记录,输出到文件
for(Text value:values) {
if (max==Integer.parseInt(value.toString().substring(2)))
{
context.write(key, value);
}
}

// context.write(new Text(key.toString()+":"+value.toString().substring(0, 2)), new IntWritable(max));
}
}

public static void main(String[] args) throws Exception {
// 设置HDFS
String ipName = "127.0.0.1";
String hdfs = "hdfs://"+ipName+":9000";
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
String jobName = "MaxTemperature";
removeOutput(conf,hdfs);

job.setJarByClass(MaxTemperature.class);
job.setMapperClass(MaxTemperatureMap.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);

// job.setCombinerClass(MaxTemperatureCombine.class);
job.setReducerClass(MaxTemperatureReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);


//3.设置作业输入和输出路径
String dataDir = "/workspace/flowStatistics/date_data"; //实验数据目录
String outputDir = "/workspace/flowStatistics/maxTemperature"; //实验输出目录
Path inPath = new Path(hdfs + dataDir);
Path outPath = new Path(hdfs + outputDir);

FileInputFormat.addInputPath(job, inPath);
FileOutputFormat.setOutputPath(job, outPath);

System.out.println("Job: " + jobName + " is running...");
if(job.waitForCompletion(true)) {
System.out.println("success!");
System.exit(0);
} else {
System.out.println("failed!");
System.exit(1);
}
}
// 这个方法是为了 避免因为output文件已经存在而报错。直接删掉上一次运行的output文件夹。
private static void removeOutput(Configuration conf, String ipPre)
throws IOException {
String outputPath = ipPre + "/workspace/flowStatistics/maxTemperature";
FileSystem fs = FileSystem.get(URI.create(outputPath), conf);
Path path = new Path(outputPath);
if (fs.exists(path)) {
fs.deleteOnExit(path);
}
fs.close();
}
}
...全文
428 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
请问你解决了吗 可以遍历两次吗
星夜丶晚晚 2019-04-24
  • 打赏
  • 举报
回复
引用 2 楼 张伯毅 的回复:
你 reduce 的时候, 获取的 Iterable<Text> values ,
在循环迭代的时候, 获取最大值的方式对么? value 是 时间 + 温度 的字符串吧.

我后面有 subString(2);把温度这个量取出来了
星夜丶晚晚 2019-04-24
  • 打赏
  • 举报
回复
引用 1 楼 zgycsmb 的回复:
检查一下counter中的redouce output record数量确实是零么?如果是,得检查逻辑。

哦,我去看一下
张伯毅 2019-04-24
  • 打赏
  • 举报
回复
你 reduce 的时候, 获取的 Iterable<Text> values , 在循环迭代的时候, 获取最大值的方式对么? value 是 时间 + 温度 的字符串吧.
zgycsmb 2019-04-24
  • 打赏
  • 举报
回复
检查一下counter中的redouce output record数量确实是零么?如果是,得检查逻辑。

20,811

社区成员

发帖
与我相关
我的任务
社区描述
Hadoop生态大数据交流社区,致力于有Hadoop,hive,Spark,Hbase,Flink,ClickHouse,Kafka,数据仓库,大数据集群运维技术分享和交流等。致力于收集优质的博客
社区管理员
  • 分布式计算/Hadoop社区
  • 涤生大数据
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧