reduce 阶段遍历对象添加到ArrayList中的问题

时间:2022-09-24 19:39:23

起初遍历values时直接把对象添加到集合中,后来输出结果和预期不符,debug时发现添加到集合中的对象的值全部是最后一个对象的值,网上百度了下,发现是reduce阶段对象重用的问题,reduce阶段的key,value分别指向一个对象,无论操作了多少个键值对,始终是这两个对象,而ArrayList的add()添加的是对象的引用地址而不是对象的值,这样add(value),当最后一个值遍历完成后,value指向的值就变成了最后一个对象的值,所以如果想要保存key,value的值(属性),需要重新new一个对象进行保存,需要添加到集合中的,应当先new一个对象,拷贝属性后再添加到集合中,不能把直接key,value添加到集合中(除非你的迭代器中只有一个值)

具体可以参考https://my.oschina.net/leejun2005/blog/131744

 1 protected void reduce(Text key, Iterable<TableBean> value,  2             Reducer<Text, TableBean, TableBean, NullWritable>.Context context) throws IOException, InterruptedException {  3         
 4         List<TableBean>    orderBeanList = new ArrayList<TableBean>();  5         TableBean pdBean  = new TableBean();  6         
 7         //分拣存储
 8         for (TableBean tableBean : value) {  9             String name = tableBean.getpName(); 10             if(StringUtils.isBlank(name)) { 11                 TableBean bean = new TableBean(); 12                 try { 13  BeanUtils.copyProperties(bean, tableBean); 14                 } catch (IllegalAccessException e) { 15  e.printStackTrace(); 16                 } catch (InvocationTargetException e) { 17  e.printStackTrace(); 18  } 19                 //orderBean
20  orderBeanList.add(bean); 21             }else { 22                 try { 23  BeanUtils.copyProperties(pdBean, tableBean); 24                 } catch (IllegalAccessException e) { 25  e.printStackTrace(); 26                 } catch (InvocationTargetException e) { 27  e.printStackTrace(); 28  } 29  } 30  } 31 
32         //遍历集合进行合并
33         for (TableBean tableBean : orderBeanList) { 34  tableBean.setpName(pdBean.getpName()); 35             //写出
36             context.write(tableBean,NullWritable.get()); 37  } 38         
39     }