package org.apache.hadoop.examples;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.RawComparator;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Partitioner;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.util.GenericOptionsParser;
/**
* hadoop的map/reduce自带的例子代码,目的是演示二次排序,
* 输入是文本文件,文本的每行是两个用空格分隔的整数,程序的输出结果是
* 按前一个整数排序,然后按后一个整数排序。应用场景是:数据join的reduce
* 端的算法。
*
* To run: bin/hadoop jar build/hadoop-examples.jar secondarysort
* in-dir out-dir
*/
public class SecondarySort {
/**
* 自定义map的输出key类型,而不是默认的Text类型,他必须实现接口comparable ,作用是输出中对key自定义排序(倒序),实现中必须提供数据的
读写方法(readFields,write)。等于(equals)和比较方法(compareTo)。
*
*/
public static class IntPair
implements WritableComparable {
private int first = 0;
private int second = 0;
/**
* Set the left and right values.
*/
public void set(int left, int right) {
first = left;
second = right;
}
public int getFirst() {
return first;
}
public int getSecond() {
return second;
}
/**
* 按编码读两个整数,编码是:读第一个整数+ Integer.MIN_VALUE+读第二个整数 + Integer.MIN_VALUE
* Encoded as: MIN_VALUE -> 0, 0 -> -MIN_VALUE, MAX_VALUE-> -1
*/
@Override
public void readFields(DataInput in) throws IOException {
first = in.readInt() + Integer.MIN_VALUE;
second = in.readInt() + Integer.MIN_VALUE;
}
/*按编码写两个整数。编码是:写第一个整数-Integer.MIN_VALUE +写第二个整数 - Integer.MIN_VALUE
*/
@Override
public void write(DataOutput out) throws IOException {
out.writeInt(first - Integer.MIN_VALUE);
out.writeInt(second - Integer.MIN_VALUE);
}
/*哈希方法,估计用于对象比较
*/ @Override
public int hashCode() {
return first * 157 + second;
}
/*等于方法,和compareTo方法用于排序,而且两者必须一致,不然,排序的结果可能不对。
*/ @Override
public boolean equals(Object right) {
if (right instanceof IntPair) {
IntPair r = (IntPair) right;
return r.first == first && r.second == second;
} else {
return false;
}
}
/** 内置的静态类,用于对象的排序比较。如果没有这个类,排序的话
用 IntPair类自身的等于和比较函数来排序*/
public static class Comparator extends WritableComparator {
public Comparator() {
super(IntPair.class);
}
/*排序方法,b1第一个对象的字节数组第一个元素,s1首个字节的长度,
l1整个字节数组的长度,
b2第二个对象的字节数组第一个元素,s2首个字节的长度,
l2整个字节数组的长度,
*/ public int compare(byte[] b1, int s1, int l1,
byte[] b2, int s2, int l2) {
return compareBytes(b1, s1, l1, b2, s2, l2);//比较对象的字节数组,遇到第一个不同立即返回
}
}
static { // 登记比较器comparator,对象 IntPair按比较器的定义排序
WritableComparator.define(IntPair.class, new Comparator());
}
/*对象的比较方法
*/ @Override
public int compareTo(IntPair o) {
if (first != o.first) {
return first < o.first ? -1 : 1;
} else if (second != o.second) {
return second < o.second ? -1 : 1;
} else {
return 0;
}
}
}
/**
* pair对象的Partitioner方法。默认是hashpartition方法。
目的是按前一个整数(firest)来决定让那个reducer来处理 */
public static class FirstPartitioner extends Partitioner{
@Override
public int getPartition(IntPair key, IntWritable value,
int numPartitions) {
return Math.abs(key.getFirst() * 127) % numPartitions;
}
}
/**
* reducer的输出按第一个整数来输出,自定义的比较器 */
public static class FirstGroupingComparator
implements RawComparator {
/*比较字节数组,注释掉该函数会报错
*/ @Override
public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
return WritableComparator.compareBytes(b1, s1, Integer.SIZE/8,
b2, s2, Integer.SIZE/8);
}
/*作用不明,注释掉改函数,不会报错。
*/ @Override
public int compare(IntPair o1, IntPair o2) {
int l = o1.getFirst();
int r = o2.getFirst();
return l == r ? 0 : (l < r ? -1 : 1);
}
}
/**mapper类,输出的key是自定义的IntPair
* Read two integers from each line and generate a key, value pair
* as ((left, right), right).
*/
public static class MapClass
extends Mapper {
private final IntPair key = new IntPair();
private final IntWritable value = new IntWritable();
@Override
public void map(LongWritable inKey, Text inValue,
Context context) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(inValue.toString());
int left = 0;
int right = 0;
if (itr.hasMoreTokens()) {
left = Integer.parseInt(itr.nextToken());
if (itr.hasMoreTokens()) {
right = Integer.parseInt(itr.nextToken());
}
key.set(left, right);
value.set(right);
context.write(key, value);
}
}
}
/**reducer类
* A reducer class that just emits the sum of the input values.
*/
public static class Reduce
extends Reducer {
private static final Text SEPARATOR =
new Text("------------------------------------------------");
private final Text first = new Text();
@Override
public void reduce(IntPair key, Iterable values,
Context context
) throws IOException, InterruptedException {
context.write(SEPARATOR, null);
first.set(Integer.toString(key.getFirst()));
for(IntWritable value: values) {
context.write(first, value);
}
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
if (otherArgs.length != 2) {
System.err.println("Usage: secondarysrot ");
System.exit(2);
}
Job job = new Job(conf, "secondary sort");//生成job对象
job.setJarByClass(SecondarySort.class);//指定jar包的名字
job.setMapperClass(MapClass.class);//设置mapper类
job.setReducerClass(Reduce.class);//设置reducer类
// group and partition by the first int in the pair
job.setPartitionerClass(FirstPartitioner.class);//设置自定义的partition类
job.setGroupingComparatorClass(FirstGroupingComparator.class);
//设置分组比较器。(按前一个整数来输出)
// the map output is IntPair, IntWritable
job.setMapOutputKeyClass(IntPair.class);//设置mapper输出的key类型
job.setMapOutputValueClass(IntWritable.class);//设置mapper输出的value类型
// the reduce output is Text, IntWritable
job.setOutputKeyClass(Text.class); //设置reducer输出的key的类型
job.setOutputValueClass(IntWritable.class);//设置reuducer输出的value的类型
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));//设置输入路径
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));//设置输出路径
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
分享到:
相关推荐
聪哥创作的一款批量保留路径清理代码注释的工具,目前兼容大部分常见的代码注释,涵盖c、java、python、php、js、html、css、mysql、node、vue、ruby等常见编程项目的注释无损清理。 2023年8月19日更新日志: 1.对...
Java代码注释是编程实践中非常重要的一个环节,它有助于提高代码的可读性和维护性。注释能够解释代码的功能、用途以及实现逻辑,使得其他开发者能更快地理解代码,尤其在团队协作中更是不可或缺。本资源"Java代码...
在IT行业中,代码注释和图形工具是程序员和开发者日常工作中不可或缺的部分。这些工具帮助他们更好地理解代码逻辑,提升团队协作效率,同时增加代码的可读性和可维护性。本篇将详细介绍“代码注释图形工具(字符画...
代码注释是编程实践中至关重要的一个环节,它有助于提高代码的可读性和可维护性。在软件开发过程中,良好的代码注释能够帮助团队成员更好地理解代码逻辑,减少误解,提高协同效率。本话题将深入探讨代码注释检测工具...
代码注释是编程实践中至关重要的一个环节,它有助于提高代码的可读性和可维护性。注释率是指源代码中的注释行数占总代码行数的比例,通常用来衡量代码的文档质量。`linecount`是一款用于统计代码注释率的工具,其...
其中,代码注释模板是一项非常实用的功能,可以帮助程序员快速生成规范、一致的注释,提高开发效率并保持代码的可读性。 在Eclipse中,用户可以自定义代码注释模板,这通常涉及到类、方法、变量等不同类型的注释...
【代码注释对齐Visual Studio AddIn】是一种增强开发效率的工具,专为Microsoft Visual Studio集成开发环境(IDE)设计。Visual Studio AddIn是Visual Studio的一种扩展机制,允许开发者自定义IDE的功能,以满足特定...
Java代码注释是编程实践中非常重要的一个环节,它有助于提高代码的可读性和维护性。在团队合作中,良好的代码注释能够帮助其他开发者更快地理解代码的功能和逻辑,节省了阅读和调试的时间。本资源包含一个“java代码...
程序员佛祖代码注释,佛祖保佑,代码无BUG
VB代码注释器是一款专为Visual Basic (VB)开发者设计的实用工具,旨在提升编程效率,简化代码注释和取消注释的操作。该插件在安装后,会在VB的集成开发环境(IDE)中添加新的功能按钮,允许用户快速地对代码进行注释...
标题中的"C/C++/Java 源代码注释清除工具"是一个专门针对这三种编程语言设计的实用程序,它的主要功能是移除源代码文件中的注释。在软件开发过程中,注释对于理解和维护代码至关重要,但在特定情况下,如代码混淆、...
在编程世界中,代码注释是开发者之间交流思想、解释代码功能的重要手段,也是保证程序健壮性的一个关键因素。代码注释率是指源代码中注释行数占总行数的比例,它反映了代码的可读性和维护性。本文将深入探讨如何通过...
《代码注释生成器——开发中的实用与趣味》 在编程世界中,代码注释是不可或缺的一部分,它有助于提升代码的可读性,方便团队协作,以及未来代码的维护。"代码注释生成器"正是这样一款工具,它能够帮助开发者们快速...
《代码注释统计软件及其重要性》 代码注释在软件开发中扮演着至关重要的角色,它是程序员之间交流思想的桥梁,是维护和扩展代码的关键工具。本文将围绕一款名为“测试软件-代码注释统计”的应用进行探讨,该软件...
在编程世界中,源代码注释是极其重要的,它们提供了对程序逻辑的解释,帮助开发者理解和维护代码。然而,在某些特定情况下,如编译优化、代码混淆或仅需执行无注释版本时,可能需要去除源代码中的注释。本文将深入...
【小米便签源代码+注释】是一款专为学习Java编程和理解软件开发流程的开发者提供的资源。这个压缩包包含了小米便签应用的完整源代码,并且每段代码都有详细的注释,使得初学者能够更好地理解和学习代码的实现逻辑。 ...
根据提供的信息,我们可以总结出以下关于“Linux内核代码注释”的相关知识点: ### Linux内核代码注释的重要性 在软件开发过程中,良好的代码注释是必不可少的。对于像Linux这样的开源项目而言更是如此,因为这...
《代码注释比统计工具详解》 在软件开发过程中,代码注释的质量和数量是衡量代码可读性、可维护性和团队协作效率的重要指标。"代码注释比统计工具"便是一个专注于此的实用工具,它能有效地帮助开发者了解项目中各...
比所谓的“C类语言源代码注释去除程序 V1.0 RemoveCNote”好用多了。而且不会太多的删错代码。几乎不用修改,而“C类语言源代码注释去除程序”修改过的代码完全不能使用。 Win8会阻止运行,选择仍然运行即可。用不用...
描述中提到的"一步注释"功能,意味着这个工具可能具有批量处理代码的能力,能够一键为代码添加注释或者格式化已有注释,使得代码规范统一,提高代码质量。这对于大型项目或者需要多人协作的工程来说,能显著提高团队...