mapreduce中的context类

博客围绕Hadoop展开,介绍了Mapper中map和Reducer中reduce里Context的作用,它用于传递数据和运行状态信息,map将数据写入context传给Reducer,Reducer处理后再写入context交给Hadoop写入hdfs系统,还提及了MapContext与ReduceContext的继承结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Mapper中的map、以及Reducer中的reduce都有一个Context的类型
1 public void map(Object key, Textvalue, Context context)
2 throwsOException,InterruptedException{
3 StringTokenizer itr = new StringTokenizer(value.toString());
4 while (itr.hasMoreTokens()) {
5 word.set(itr.nextToken());
6 context.write(word, one);
7 }
8 }
9
10 public void reduce(Text key, Iterable values,Contextcontext)
11 throws IOException,InterruptedException {
12 int sum = 0;
13 for (IntWritable val : values){
14 sum += val.get();
15 }
16 result.set(sum);
17 context.write(key, result);
18 }
可以了解到,context应该是用来传递数据以及其他运行状态信息,map中的key、value写入context,让它传递给Reducer进行reduce,而reduce进行处理之后数据继续写入context,继续交给Hadoop写入hdfs系统。
从继承结构可以看出MapContext与ReduceContext均继承TaskInputOutputContext,没有重写继承而来的方法,所以它们继承的都是一致的)
java.lang.object
org.apache.hadoop.mapreduce.JobContext
org.apache.hadoop.mapreduce.TaskAttemptContext
org.apache.hadoop.mapreduce.TaskInputOutputContext<KEYIN,VALUEIN,KEYOUT,VALUEOUT> org.apache.hadoop.mapreduce.MapContext<KEYIN,VALUEIN,KEYOUT,VALUEOUT> org.apache.hadoop.mapreduce.ReduceContext<KEYIN,VALUEIN,KEYOUT,VALUEOUT>

### 使用 MapReduce 实现鸢尾花数据集分 #### 设计思路 为了利用MapReduce框架实现KNN算法对鸢尾花数据集进行分,整个过程可以分为几个阶段来完成。首先是对输入数据的预处理,接着是Mapper阶段计算各个测试样本到训练集中所有点的距离;随后进入Combiner阶段汇总部分结果以减少网络传输量;最后由Reducer负责最终决策别。 #### 预处理 在正式运行之前,需要准备好用于训练和验证的数据文件。通常会将原始CSV格式的Iris数据集转换成适合HDFS存储的形式,并按照一定比例划分为训练集与测试集[^2]。 #### Mapper (KNN_Mapper.java) 此组件接收来自HDFS上的键值对形式记录作为输入,其中key代表偏移位置而value则是具体的一条观测记录字符串表示法。对于每一条读取进来的记录,如果属于训练集合,则直接输出其特征向量及其标签构成的新键值对;若是测试样本则需遍历已知的所有训练样本来求解欧氏距离并连同待测项ID一起发出等待后续聚合操作。 ```java public static class KNN_Mapper extends Mapper<LongWritable, Text, IntWritable, PairOfWritables> { @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String[] line = value.toString().split(","); double[] features = Arrays.stream(line).mapToDouble(Double::parseDouble).toArray(); if (isTrainingSample(key.get())) { // 判断是否为训练样本 context.write(new IntWritable(-1), new PairOfWritables(new VectorWritable(features), new LabelWritable(getLabel()))); } else { List<Pair<Double, Integer>> distances = calculateDistancesFromAllTrainSamples(features); for(Pair<Double,Integer> p : distances){ context.write(new IntWritable(p.getValue()),new PairOfWritables(new DistanceWritable(p.getKey()),new VectorWritable(features))); } } } private boolean isTrainingSample(long offset){/*...*/} } ``` #### Combiner (可选优化措施) 考虑到当训练规模较大时可能会造成过多中间状态传递给reducer端从而影响效率的问题,在这里引入了一个简单的combiner机制用来提前筛选出k个最近邻居的信息发送出去即可满足需求[^3]。 ```java public static class KNN_Combiner extends Reducer<IntWritable,PairOfWritables,IntWritable,PairOfWritables>{ int k; public void setup(Context context)throws IOException{ Configuration conf=context.getConfiguration(); this.k=Integer.parseInt(conf.get("k")); } @Override protected void reduce(IntWritable key, Iterable<PairOfWritables> values,Context context)throws IOException,InterruptedException{ PriorityQueue<Pair<DistanceWritable,VectorWritable>> queue=new PriorityQueue<>(Comparator.comparing(o->o.getLeft())); for(var v:values){ queue.offer(new ImmutablePair<>((DistanceWritable)v.getLeft(),(VectorWritable)v.getRight())); while(queue.size()>this.k){ queue.poll(); } } for(;!queue.isEmpty();){ var item=queue.poll(); context.write(key,new PairOfWritables(item.getLeft(),item.getRight())); } } } ``` #### Reducer (KNN_Reducer.java) 接受到来自mapper层经过可能存在的组合器初步过滤后的候选邻近距离列表后,依据设定好的参数`k`选取最接近前几名对应的别统计频次最高者即为目标预测结果。 ```java public static class KNN_Reducer extends Reducer<IntWritable,PairOfWritables,NullWritable,Text>{ int k; @Override protected void setup(Context context)throws IOException{ Configuration conf=context.getConfiguration(); this.k=Integer.parseInt(conf.get("k")); } @Override protected void reduce(IntWritable key,Iterable<PairOfWritables> values,Context context)throws IOException,InterruptedException{ HashMap<Integer,Integer> labelCount=new HashMap<>(); Iterator<PairOfWritables> iterator=values.iterator(); for(int i=0;i<k&&iterator.hasNext();i++){ DoubleWritable distance=(DoubleWritable)((PairOfWritables)(iterator.next())).getLeft(); VectorWritable vector=((PairOfWritables)value).getRight(); // 假设vector中包含了label信息... int predictedLabel=getPredictedLabel(vector); labelCount.merge(predictedLabel, 1, Integer::sum); } Entry<Integer, Integer> mostFrequentEntry=labelCount.entrySet() .stream() .max(Map.Entry.<Integer, Integer>comparingByValue()) .orElseThrow(IllegalStateException::new); context.write(NullWritable.get(),new Text(String.valueOf(mostFrequentEntry.getKey()))); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值