2013-06-07 1 views
2

Я решил создать свой собственный класс 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); 
} 
} 
+1

Вы используете единственный редуктор? –

ответ

4

по умолчанию разметки является HashPartitioner, который использует метод hashCode чтобы определить, какой редуктор должен отправить пару K, V в.

Однажды в редукторе (или если вы используете Комбинер, который работает на стороне карты), метод compareTo используется для сортировки ключей, а затем используется (по умолчанию) для сравнения, следует ли группировать последовательные ключи и их связанные значения уменьшены на одной и той же итерации.

Если вы не используете ключ переменной cliente и только переменную orderNumber в методе compareTo, то любой ключ с тем же orderNumber будет иметь свои значения уменьшаются вместе - независимо от значения cliente (что вы в настоящее время наблюдается)

+0

Спасибо, Крис. В любом случае, разве вы не думаете, что было бы лучше, если бы hashCode использовался для группировки вместо compareTo? – ISegundo

+0

HashPartitioner - это только один разделитель, доступный для hadoop, и использование метода compareTo позволяет выполнять вторичную сортировку в редукторе, что позволяет использовать другие функции –

Смежные вопросы