2013-11-28 3 views
1

В моем методе reduce я хочу использовать переменную TreeMapreduceMap для суммирования входящих значений ключа. Однако эта карта теряет свое состояние при каждом вызове метода reduce. Впоследствии Hadoop печатает только самое последнее значение (плюс добавленные тестовые значения), которое помещается в TreeMap. Почему это? Он работает, как я намереваюсь в моем методе map.Почему TreeMap сбрасывается после каждого метода сокращения?

public static class TopReducer extends 
      Reducer<Text, IntWritable, Text, IntWritable> { 

     private TreeMap<Text, Integer> reducedMap = new TreeMap<Text, Integer>(); 

     @Override 
     public void reduce(Text key, Iterable<IntWritable> values, 
       Context context) throws IOException, InterruptedException { 

      int sum = 0; 
      String strValues = ""; 
      for (IntWritable value : values) { 
       sum += value.get(); 
       strValues += value.get() + ", "; 
      } 
      System.out.println("Map size Before: " +reducedMap); 
      Integer val = sum; 
      if (reducedMap.containsKey(key)) 
       val += reducedMap.get(key); 
      // Only add, if value is of top 30. 
      reducedMap.put(key, val); 
      System.out.println("Map size After: " +reducedMap); 
      reducedMap.put(new Text("test"), 77777); 

      System.out.println("REDUCER: rcv: (" + key + "), " + "(" + sum 
        + "), (" + strValues + "):: new (" + val + ")"); 
     } 

     /** 
     * Flush top 30 context to the next phase. 
     */ 
     @Override 
     protected void cleanup(Context context) throws IOException, 
       InterruptedException { 
      System.out.println("-----FLUSHING TOP " + TOP_N 
        + " MAPPING RESULTS-------"); 
      System.out.println("MapSize: " + reducedMap); 
      int i = 0; 
      for (Entry<Text, Integer> entry : entriesSortedByValues(reducedMap)) { 
       System.out.println("key " + entry.getKey() + ", value " 
         + entry.getValue()); 
       context.write(entry.getKey(), new IntWritable(entry.getValue())); 

       if (i >= TOP_N) 
        break; 
       else 
        i++; 
      } 
     } 
    } 

ответ

3

Hadoop повторно использует ссылки на объекты для целей эффективности - поэтому, когда вы звоните reducedMap.put(key, val) ключевое значение будет соответствовать ключ уже в карте (потому что Hadoop только заменить содержимое вашего ключевого объекта, не дал вам новая ссылка на новый объект с новым содержимым). Это фактически то же самое, как вызов следующее:

Text key = new Text("x"); 
reducedMap.put(key, val); // map will be of size 1 
key.set("y"); 
reducedMap.put(key, val); // map will still be of size 1 
          // as it will be comparing key to the itself 
          // and just updating the mapped value val 

Вам нужно сделать глубокую копию ключа, прежде чем положить его в карту:

reducedMap.put(new Text(key), val) 
+0

спасибо. Работает, конечно. – feder

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