Mismo elemento en una lista

bornex

Hola gente, tengo un pequeño problema con un código que tengo "casi" hecho.

El problema es el siguiente:

Tengo un archivo de texto, concretamente un archivo con las coordenadas de cada fotograma de un SpriteSheet, y lo quiero procesar.

El archivo tiene esta pinta:

p1_duck = 365 98 69 71
p1_front = 0 196 66 92
p1_hurt = 438 0 69 92
p1_jump = 438 93 67 94
p1_stand = 67 196 66 92
p1_walk01 = 0 0 72 97
p1_walk02 = 73 0 72 97
p1_walk03 = 146 0 72 97
p1_walk04 = 0 98 72 97
p1_walk05 = 73 98 72 97
p1_walk06 = 146 98 72 97
p1_walk07 = 219 0 72 97
p1_walk08 = 292 0 72 97
p1_walk09 = 219 98 72 97
p1_walk10 = 365 0 72 97
p1_walk11 = 292 98 72 97

Tengo un código hecho que me recorre cada linea, la recorta con split y mete en un array los datos NUMÉRICOS que a su vez se guardan en un ArrayList para tenerlo todo junto.

El código que hace eso es:

public ArrayList<int[]> procesar(File file) throws FileNotFoundException {
		String linea = "";
		int [] datos = new int [4];
		FileReader fr = new FileReader(file);
		BufferedReader br = new BufferedReader(fr);
		Scanner sc = new Scanner(br);
		sc.useDelimiter(this.separador);
		while (sc.hasNextLine()) {
			linea = sc.nextLine();
			for(int i = 0, j = 2; i < datos.length; i++, j++){
				String[] tokens = linea.split(this.separador);
				datos[i] = Integer.parseInt(tokens[j]);
			}
			lista.add(datos);
		}
		sc.close();
		return lista;
	}

El caso es que le estoy dando vueltas al depurador y no logro encontrar el fallo de porque me mete siempre el mismo objeto (el mismo array con los mismos datos) en toda la lista. Si accedo a cualquier objeto de la lista y al primer elemento de éste, siempre me da el de la última línea del archivo.

Bueno espero haberme explicado con claridad y a ver si me podéis echar una mano :P

MTX_Anubis

Porque estás trabajando con el mismo array todo el rato, debes crear uno nuevo por línea.

1 1 respuesta
bornex

#2 Ok, gracias solucionado, pero tengo una pregunta, porque no pasa lo mismo con la variable ¿String linea?.

Yo pensaba que cada vez que entra en el bucle for, sobrescribe los valores del array datos.

3 respuestas
Mewtwo

#3 es lo que hace el bucle for xD sobrescribir el array que tiene la variable datos , lo unico que como añades esa variable a al array estas diciendo que guarde esa direccion de memoria que es datos , por eso al cambiar datos , se cambia todo el array , no se si me explico bien.

Con linea pasaria lo mismo lo unico que a ti te interesa que se cambie el valor que esta guardado en esa direccion de memoria por tanto se sobrescribe sin problemas

pd:si no me he explicado bien y no lo entiendes luego te lo intento explicar mejor

1 respuesta
elkaoD

#3 cuando haces lista.add(datos) no estás haciendo una copia. Si sólo creas un "int [] datos = new int [4];" al principio, siempre añades el mismo (y siempre estás cambiando los valores del mismo array por tanto).

En otra palabras, el "int [] datos = new int [4];" va dentro del while, no fuera.

1 respuesta
bornex

#4 Jajaja, muchas gracias por explicármelo, la verdad que no lo he entendido muy bien como me lo has dicho, pero en #5 si me ha quedado mas claro. Muchas gracias ;)

1 respuesta
Mewtwo

#6 es que la explicacion es mas sencilla con dibujitos xD yo la primera vez que me lo explicaron tambien tarde un poco en pillarlo , puedes buscar como funcionan los punteros en pascal que es un lenguaje muy sencillo y funcionan de forma similar los punteros y los objetos

MTX_Anubis

#3 Estrás creando un String nuevo cada vez aquí:

linea = sc.nextLine();

nextLine() te devuelve un String nuevo (los strings son inmutables en java). El problema con el array es que tu variable no es el array, es una referencia a la primera dirección de éste (en java no recuerdo si es así pero no debería cambiar mucho). A ver si te lo puedo explicar sin dibujos para que se entienda bien:

int [] datos = new int [4];

Eso lo que hace es crear un array de 4 integers. Hasta ahí bien. la variable datos referencia a ese array. Cuando haces datos[x] lo que haces es, dentro de esas 4 direcciones que se han reservado, cambiar el valor interno pero la dirección a la que apunta datos no varía.

Así que lo que estás haciendo en cada iteración es añadir la referencia a la que apunta datos y cambiando todos los valores que tiene. Como siempre se apunta al mismo sitio, cuando accedes lo estás haciendo siempre sobre el mismo array.

1 2 respuestas
bornex

#8 OK. Grandioso, muchísimas gracias por la molestia,no lo llegue a entender muy bien con los anteriores pero ahora esta clarísimo. :)

elkaoD

#8 en Java datos referencia al array en sí mismo, y no es equivalente a array[0] como en C. Desconozco cómo lo representa internamente la JVM una vez traducido a bytecode, pero int [] datos2 = datos; compilaría, mientras que int datos2 = datos; no.

Trivia: en C también se puede hacer 0[array] (ejemplo). Esto es porque a[b] no es más que "syntax sugar" para *(a + b).

El dato inútil del día.

1

Usuarios habituales

  • elkaoD
  • bornex
  • MTX_Anubis
  • Mewtwo