reduce中Iterator<ritable>的循环陷阱

本文探讨在使用Hadoop MapReduce处理数据时遇到的reduce侧关联问题,详细解释了问题产生的原因及解决方案,包括如何避免引用对象导致的问题,并提供了优化循环处理的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

初学hadoop,尝试练习mapreduce中reduce侧关联例子的时候,越到莫名其妙的问题:

设计思路:对map过来的key,list结构进行三次循环,首先转成list,第二个是获取主键来源的信息行(主表数据,唯一一条),然后在循环第三次,对剩余的数据加上找出来的主表数据。

第一次循环代码,转换成list:

List<JoinWritable> rows = new ArrayList<JoinWritable>();
			for (JoinWritable record : values) {
				
				rows.add(record);
			}
第二次找出主表数据

for (JoinWritable record : records) {
				if (FILE_NAME_MASTER.equals(record.getFileName())) {
					records.remove(record);
					return record;
				}
			}
第三次彻底拼接结果

/* 2.判断reduce中的数据集,如果小于2,直接返回因为此处是内连接!!! */
			if (records.size() < 2) {
				return;
			} else {
				JoinWritable masterRecord = this
						.searchAndRemoveMasterKeyRecord(records);
				if (masterRecord == null) {
					throw new RuntimeException("输入数据错误,没有对应主键【"
							+ key.toString() + "】的主表记录");
				}
				for (JoinWritable record : records) {
					context.write(key, new Text(masterRecord.toString() + ","
							+ record.toString()));
				}
			}

逻辑看上去并没有问题,在马上下班的情况下,运行了次,结果抛出了异常,而且是在
throw new RuntimeException("输入数据错误,没有对应主键【"
							+ key.toString() + "】的主表记录");
回家后,又走了下,还是如此的错误!弄了好久,发现每次到最后的时候list中数据都是一样的!这不科学呀,偶尔间在网上看到了一个信息,说hadoop的reduce中,Iterable循环Writable的时候都是指向的同一个对象,如果保存这个对象,实际是保存的引用!

将第一个循环代码改为

for (JoinWritable record : values) {
				//此处真他妈的坑爹 直接add会引用一个对象!!!
				rows.add(new JoinWritable(record));
			}
可以解决这个问题!当然有更好的解决方法,以后会另有说明。

这个问题可能是hadoop推荐只用一次循环来处理所有的结果。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值