問題描述:
輸入文件格式如下:
name1 2
name3 4
name1 6
name1 1
name3 3
name1 0
要求輸出的文件格式如下:
name1 0,1,2,6
name3 3,4
要求是按照第一列分組,name1與name3也是按照順序排列的,組內升序排序。
思路:
常規的輸出,無法排序key所對應的多個值的順序。為了排序組內中的值,需要將key與value放在同一個組。Job中有兩個方法setGroupingComparatorClass和setSortComparatorClass,可以利用這兩個方法來實現組內排序。但是這些排序都是基於key的,則就要將key和value定義成組合鍵。
但是必須要保證第一列相同的全部都放在同一個分區中,則就需要自定義分區,分區的時候只考慮第一列的值。由於partitioner僅僅能保證每一個reducer接受同一個name的所有記錄,但是reducer仍然是通過鍵進行分組的分區,也就說該分區中還是按照鍵來分成不同的組,還需要分組只參考name值
先按照name分組,再在name中內部進行排序。
解決方法:
運用自定義組合鍵的策略,將name和1定義為一個組合鍵。在分區的時候只參考name的值,即繼承partitioner。
由於要按照name分組,則就需要定義分組策略,然後設置setGroupingComparatorClass。
setGroupingComparatorClass主要定義哪些key可以放置在一組,分組的時候會對組合鍵進行比較,由於這裡只需要考慮組合鍵中的一個值,則定義實現一個WritableComparator,設置比較策略。
對於組內的排序,可以利用setSortComparatorClass來實現,
這個方法主要用於定義key如何進行排序在它們傳遞給reducer之前,
這裡就可以來進行組內排序。
具體代碼:
Hadoop版本號:hadoop1.1.2
自定義組合鍵
package whut;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
//自定義組合鍵策略
//java基本類型數據
public class TextInt implements WritableComparable{
//直接利用java的基本數據類型
private String firstKey;
private int secondKey;
//必須要有一個默認的構造函數
public String getFirstKey() {
return firstKey;
}
public void setFirstKey(String firstKey) {
this.firstKey = firstKey;
}
public int getSecondKey() {
return secondKey;
}
public void setSecondKey(int secondKey) {
this.secondKey = secondKey;
}
@Override
public void write(DataOutput out) throws IOException {
// TODO Auto-generated method stub
out.writeUTF(firstKey);
out.writeInt(secondKey);
}
@Override
public void readFields(DataInput in) throws IOException {
// TODO Auto-generated method stub
firstKey=in.readUTF();
secondKey=in.readInt();
}
//map的鍵的比較就是根據這個方法來進行的
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
TextInt ti=(TextInt)o;
//利用這個來控制升序或降序
//this本對象寫在前面代表是升序
//this本對象寫在後面代表是降序
return this.getFirstKey().compareTo(ti.getFirstKey());
}
}
分組策略
package whut;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
//主要就是對於分組進行排序,分組只按照組建鍵中的一個值進行分組
public class TextComparator extends WritableComparator {
//必須要調用父類的構造器
protected TextComparator() {
super(TextInt.class,true);//注冊comparator
}
@Override
public int compare(WritableComparable a, WritableComparable b) {
// TODO Auto-generated method stub
TextInt ti1=(TextInt)a;
TextInt ti2=(TextInt)b;
return ti1.getFirstKey().compareTo(ti2.getFirstKey());
}
}