我在映射器中发送了一些数据,当我尝试在Reducer中读取它们时,它们发生了一些变化。在简历中,我使用 set 函数填充数据,然后使用 get 函数在化简器中读取它们。我不明白为什么如果我做一个println,数据是不同的。
我发送的数据在一个名为"ValorFechaHora"的类中,3个变量Medicion,Fecha和Hora:
public class ValorFechaHora implements Writable {
private IntWritable Medicion;
private Text Fecha;
private Text Hora;
public void ValorFechaHora(){
}
public void ValorFechaHora(IntWritable Medicion, Text Fecha, Text Hora){
setMedicion(Medicion);
setFecha(Fecha);
setHora(Hora);
}
public IntWritable getMedicion() {
return Medicion;
}
public void setMedicion(IntWritable medicion) {
Medicion = medicion;
}
public Text getFecha() {
return Fecha;
}
public void setFecha(Text fecha) {
Fecha = fecha;
}
public Text getHora() {
return Hora;
}
public void setHora(Text hora) {
Hora = hora;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((Fecha == null) ? 0 : Fecha.hashCode());
result = prime * result + ((Hora == null) ? 0 : Hora.hashCode());
result = prime * result
+ ((Medicion == null) ? 0 : Medicion.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ValorFechaHora other = (ValorFechaHora) obj;
if (Fecha == null) {
if (other.Fecha != null)
return false;
} else if (!Fecha.equals(other.Fecha))
return false;
if (Hora == null) {
if (other.Hora != null)
return false;
} else if (!Hora.equals(other.Hora))
return false;
if (Medicion == null) {
if (other.Medicion != null)
return false;
} else if (!Medicion.equals(other.Medicion))
return false;
return true;
}
public void readFields(DataInput in) throws IOException {
Medicion = new IntWritable(in.readInt());
Fecha = new Text(in.readLine());
Hora = new Text(in.readLine());
}
public void write(DataOutput out) throws IOException {
Medicion.write(out);
Fecha.write(out);
Hora.write(out);
}
}
在这里你可以看到我的映射器:
public static class LogsMapper extends
Mapper<LongWritable, Text, Text, ValorFechaHora> {
//En el mapper emitimos lo que leemos. Key = Dirección MAC. Value = Medición + Fecha + Hora
private Text outKey = new Text();
private ValorFechaHora outValue = new ValorFechaHora();
@Override
protected void map(LongWritable offset, Text line, Context context)
throws IOException, InterruptedException {
// Utilizamos row_auxiliar y row para leer los datos correctos (El offset no nos interesa)
// Ejemplo de dato de entrada tras salir del filtrado básico "2536816 -47dB;8C:3A:E3:92:CB:3E;2014-11-12;14:22:20.795806"
String row_auxiliar[] = line.toString().split("t");
String row[] = row_auxiliar[1].split(";");
// Los datos en row quedan... ---> row[0]= Medicion row[1]= MAC row[2]= Fecha row[3]= Hora
//Elegimos la MAC como key
outKey = new Text(row[1]);
//Elegimos la Medicion, Fecha y Hora como value
outValue.setMedicion(new IntWritable(Integer.valueOf(row[0].substring(0,3))));
outValue.setFecha(new Text(row[2]));
outValue.setHora(new Text(row[3]));
context.write(outKey, outValue);
};
这是我的减速器:
public static class MaxReducer extends
Reducer<Text, ValorFechaHora, Text, Text> {
//En el reduce por ahora únicamente contamos el número de veces que ha sido la MAC registrada
protected void reduce(Text MAC,
Iterable<ValorFechaHora> values, Context context)
throws IOException, InterruptedException {
Text outKey = new Text();
Text outValue = new Text();
outKey = MAC;
int sum = 0;
for(ValorFechaHora val : values){
System.out.println("1" + " " + val.getMedicion().toString());
System.out.println("2" + " " + val.getFecha().toString());
System.out.println("3" + " " + val.getHora().toString());
sum = sum +1;
}
outValue = new Text(Integer.toString(sum));
context.write(outKey, outValue);
};
好吧,我不明白为什么当我做 bucle 时,化简器中的变量 val.getFecha().toString() 与映射器中的变量 outKey.getFecha().toString 不同
蒂亚
了错误的方法调用来填充 Text 对象。您应该使用 Text 对象的 readFields 方法。
当前,您正在尝试通过构造函数填充 Text 对象,该构造函数接受字符串作为其参数。不能只使用 in.readLine 从 DataInput 对象读回字符串,因为文本对象将序列化为数据流,而无需终止换行符。
要解决此问题,您应该重用,您应该初始化变量,然后只使用 readFields 方法(这可能会在您的代码中产生其他连锁反应,因为您当前没有使用对象重用模式(这比为每个 K/V 对象创建新对象更有效):
private IntWritable Medicion = new IntWritable();
private Text Fecha = new Text();
private Text Hora = new Text();
public void readFields(DataInput in) {
Medicion.readFields(in);
Fecha.readFields(in);
Hora.readFields(in);
}
否则,要保持代码原样(但效率较低),只需更新 readFields 方法,如下所示:
public void readFields(DataInput in) {
Medicion = new Text();
Medicion.readFields(in);
Fecha = new Text();
Fecha.readFields(in);
Hora = new Text();
Hora.readFields(in);
}
我不太明白为什么会发生这种情况,但我解决了在"ValorFechaHora"类中更改这些代码行的问题
public void readFields(DataInput in) throws IOException {
Medicion = new IntWritable(in.readInt());
//Fecha = new Text(in.readLine());
//Hora = new Text(in.readLine());
//Those two lines for these ones:
Fecha = new Text(Text.readString(in));
Hora = new Text(Text.readString(in));
秋