当我在化简器中读取它们时,映射器中发送的文本/字符串值是错误的



我在映射器中发送了一些数据,当我尝试在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));

相关内容

  • 没有找到相关文章

最新更新