Я решил создать свой собственный класс WritableComparable, чтобы узнать, как Hadoop работает с ним. Поэтому я создаю класс Order с двумя переменными экземпляра (orderNumber cliente) и реализовал необходимые методы. Я также использовал генераторы Eclipse для getters/setters/hashCode/equals/toString.Не следует Hadoop group <ключ, (список значений) в редукторе только на основе hashCode?
В сравнении, я решил использовать только переменную orderNumber.
Я создал простую задачу MapReduce только для подсчета вхождения порядка в наборе данных. По ошибке один из моих тестовых записей Ita вместо ITA, как вы можете увидеть здесь:
123 Ita
123 Itá
123 Itá
345 Carol
345 Carol
345 Carol
345 Carol
456 Iza Smith
Как я понимаю, первая запись должна рассматриваться как иной порядок, потому что запись 1 хэш-код является де отличаются от записи 2 и 3 хэш-кодов.
Но в фазе уменьшения 3 записи сгруппированы вместе. Как вы можете увидеть здесь:
Order [cliente=Ita, orderNumber=123] 3
Order [cliente=Carol, orderNumber=345] 4
Order [cliente=Iza Smith, orderNumber=456] 1
Я думал, что он должен иметь линию для ITA записей со счетом 2 и Ит должен рассчитывать 1.
Ну как я использовал только ORDERNUMBER в CompareTo, я пытался использовать String cliente в этом методе (прокомментирован код ниже). И тогда это сработало, как я ожидал.
Итак, это ожидаемый результат? Не следует ли использовать hashCode для группировки ключа и его значений?
Вот класс Order (I опущен геттеры/сеттеры):
public class Order implements WritableComparable<Order>
{
private String cliente;
private long orderNumber;
@Override
public void readFields(DataInput in) throws IOException
{
cliente = in.readUTF();
orderNumber = in.readLong();
}
@Override
public void write(DataOutput out) throws IOException
{
out.writeUTF(cliente);
out.writeLong(orderNumber);
}
@Override
public int compareTo(Order o) {
long thisValue = this.orderNumber;
long thatValue = o.orderNumber;
return (thisValue < thatValue ? -1 :(thisValue == thatValue ? 0 :1));
//return this.cliente.compareTo(o.cliente);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cliente == null) ? 0 : cliente.hashCode());
result = prime * result + (int) (orderNumber^(orderNumber >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Order other = (Order) obj;
if (cliente == null) {
if (other.cliente != null)
return false;
} else if (!cliente.equals(other.cliente))
return false;
if (orderNumber != other.orderNumber)
return false;
return true;
}
@Override
public String toString() {
return "Order [cliente=" + cliente + ", orderNumber=" + orderNumber + "]";
}
Вот код MapReduce:
public class TesteCustomClass extends Configured implements Tool
{
public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Order, LongWritable>
{
LongWritable outputValue = new LongWritable();
String[] campos;
Order order = new Order();
@Override
public void configure(JobConf job)
{
}
@Override
public void map(LongWritable key, Text value, OutputCollector<Order, LongWritable> output, Reporter reporter) throws IOException
{
campos = value.toString().split("\t");
order.setOrderNumber(Long.parseLong(campos[0]));
order.setCliente(campos[1]);
outputValue.set(1L);
output.collect(order, outputValue);
}
}
public static class Reduce extends MapReduceBase implements Reducer<Order, LongWritable, Order,LongWritable>
{
@Override
public void reduce(Order key, Iterator<LongWritable> values,OutputCollector<Order,LongWritable> output, Reporter reporter) throws IOException
{
LongWritable value = new LongWritable(0);
while (values.hasNext())
{
value.set(value.get() + values.next().get());
}
output.collect(key, value);
}
}
@Override
public int run(String[] args) throws Exception {
JobConf conf = new JobConf(getConf(),TesteCustomClass.class);
conf.setMapperClass(Map.class);
// conf.setCombinerClass(Reduce.class);
conf.setReducerClass(Reduce.class);
conf.setJobName("Teste - Custom Classes");
conf.setOutputKeyClass(Order.class);
conf.setOutputValueClass(LongWritable.class);
conf.setInputFormat(TextInputFormat.class);
conf.setOutputFormat(TextOutputFormat.class);
FileInputFormat.setInputPaths(conf, new Path(args[0]));
FileOutputFormat.setOutputPath(conf, new Path(args[1]));
JobClient.runJob(conf);
return 0;
}
public static void main(String[] args) throws Exception {
int res = ToolRunner.run(new Configuration(),new TesteCustomClass(),args);
System.exit(res);
}
}
Вы используете единственный редуктор? –