1,Text格式只在传输过程中使用(context.write和value),map/reduce正文中都需要将value转化为String类型再使用,如果直接将value加入treemap则会将其视为对象引用,导致treemap中所有的值都相等!
2,如果输出路径存在就删除
Path in = new Path(args[0]); //如果存在路径就删除之
Path out = new Path(args[1]);
FileSystem fileSystem = FileSystem.get(new URI(in.toString()), new Configuration());
if (fileSystem.exists(out)) {
fileSystem.delete(out, true);
}
3,二次排序使用自定义group方法时,grouper类中必须实现如下的compare方法,否则grouper不会生效,也不会报错。
同时WritableComparator面对的都是序列化对象的比较问题,都需要将数据反序列化为对象之后再进行比较,因此必须提供空参构造函数用于反射出原来的对象,类型为要还原的对象类型,即key的类型
public int compare(WritableComparable m,WritableComparable n){
return ((udf_Pair)m).p1.compareTo(((udf_Pair)n).p1);//此处可自定义
}
4,二次排序使用自定义udf_pair类,必须实现Writable, WritableComparable<udf_Pair>接口,必须实现相关方法
@Override
public void readFields(DataInput in) throws IOException {//必须实现
p1.readFields(in);
p2.readFields(in);
}
@Override
public void write(DataOutput out) throws IOException {
p1.write(out);
p2.write(out);
}
5,map方法初始输入类型为(LongWritable,Text,Context),key为读取文件的偏移量,value为Text的行记录,reduce方法输入类型为(key,Iterable<value>,Context),使用context的write方法输出
6,reducer的key对象是唯一的持续的,对不同的组只是key的属性值有变化!若要将key放入内存的map或list中,一定要使用new Text(key)新建对象。
reducer的values对象、values的iterator对象、values的iterator对象的next()的返回对象也都是唯一的持续的,若在一个上下文环境中调用了多次,也需要使用new Text(iterator.next())新建对象。
7,reducer在读取sort后的数据时,先返回key和一个迭代器,迭代value的过程中每读取一个值就使用group类的compare方法比较新的key与当前key是否一致,一致则迭代继续,否则本轮reduce的值迭代结束,实现类似分组的效果,也因为这个原因,每组的key取的是第一个。
8,自定义outputformat类时,经常会使用fs=FileSystem.get(job.getConfiguration())来获取文件系统,之后再进行create或者其他操作,此时一定要注意fs.defaultFS的取值,如果使用core.xml默认的hdfs,而create传入的uri为file:///,则会报错