Matrices y datos tabulares
Un array organiza una secuencia. Cuando los datos tienen filas y columnas —ventas por tienda y mes, notas por alumno y prueba— podemos usar un array bidimensional, al que llamaremos matriz.
Crear una matriz
int[][] ventas = new int[3][4];
Esta matriz tiene tres filas y cuatro columnas. Los valores int comienzan en 0.
También podemos inicializarla con datos:
int[][] ventas = {
{10, 12, 9, 15},
{7, 11, 13, 8},
{14, 10, 12, 16}
};
Cada bloque interior representa una fila.
Acceder y modificar
Necesitamos dos índices:
System.out.println(ventas[0][0]); // 10
System.out.println(ventas[2][3]); // 16
ventas[1][2] = 14;
El primer índice selecciona la fila y el segundo, la columna. Ambos empiezan en 0.
Práctica inmediata
En una tabla de dos alumnos y tres notas, muestra la segunda nota del primer alumno y cambia la tercera del segundo:
int[][] notas = {
{7, 8, 6},
{5, 9, 7}
};
System.out.println(notas[0][1]); // 8
notas[1][2] = 10;
Longitud de filas y columnas
System.out.println(ventas.length); // filas: 3
System.out.println(ventas[0].length); // columnas de la fila 0: 4
matriz.length cuenta filas. matriz[fila].length cuenta los elementos de esa fila.
Recorrer con bucles anidados
for (int fila = 0; fila < ventas.length; fila++) {
for (int columna = 0; columna < ventas[fila].length; columna++) {
System.out.print(ventas[fila][columna] + " ");
}
System.out.println();
}
Por cada fila, el bucle interior recorre todas sus columnas. Usar ventas[fila].length hace que el recorrido también sea seguro si las filas tienen longitudes diferentes.
Sumar por filas
for (int fila = 0; fila < ventas.length; fila++) {
int sumaFila = 0;
for (int columna = 0; columna < ventas[fila].length; columna++) {
sumaFila += ventas[fila][columna];
}
System.out.println("Fila " + fila + ": " + sumaFila);
}
sumaFila se reinicia al comenzar cada fila. Si se declarara antes del bucle exterior, acumularía también las filas anteriores.
Sumar por columnas
En una matriz rectangular podemos recorrer primero las columnas:
for (int columna = 0; columna < ventas[0].length; columna++) {
int sumaColumna = 0;
for (int fila = 0; fila < ventas.length; fila++) {
sumaColumna += ventas[fila][columna];
}
System.out.println("Columna " + columna + ": " + sumaColumna);
}
Este ejemplo presupone que hay al menos una fila y que todas tienen el mismo número de columnas.
Buscar un valor
int buscado = 13;
int filaEncontrada = -1;
int columnaEncontrada = -1;
for (int fila = 0; fila < ventas.length; fila++) {
for (int columna = 0; columna < ventas[fila].length; columna++) {
if (ventas[fila][columna] == buscado) {
filaEncontrada = fila;
columnaEncontrada = columna;
}
}
}
System.out.println(filaEncontrada + ", " + columnaEncontrada);
Los dos índices describen una celda. En esta versión, si el valor se repite, conservamos la última coincidencia.
Programa completo: temperaturas semanales
public class TemperaturasSemanales {
public static void main(String[] args) {
int[][] temperaturas = {
{18, 20, 21, 19},
{17, 22, 23, 20},
{16, 19, 20, 18}
};
mostrarTabla(temperaturas);
mostrarPromediosPorFila(temperaturas);
mostrarMaximo(temperaturas);
}
public static void mostrarTabla(int[][] datos) {
for (int fila = 0; fila < datos.length; fila++) {
for (int columna = 0; columna < datos[fila].length; columna++) {
System.out.print(datos[fila][columna] + " ");
}
System.out.println();
}
}
public static void mostrarPromediosPorFila(int[][] datos) {
for (int fila = 0; fila < datos.length; fila++) {
int suma = 0;
for (int valor : datos[fila]) {
suma += valor;
}
double promedio = (double) suma / datos[fila].length;
System.out.println("Promedio fila " + fila + ": " + promedio);
}
}
public static void mostrarMaximo(int[][] datos) {
int maximo = datos[0][0];
int mejorFila = 0;
int mejorColumna = 0;
for (int fila = 0; fila < datos.length; fila++) {
for (int columna = 0; columna < datos[fila].length; columna++) {
if (datos[fila][columna] > maximo) {
maximo = datos[fila][columna];
mejorFila = fila;
mejorColumna = columna;
}
}
}
System.out.println("Máxima: " + maximo + " en "
+ mejorFila + ", " + mejorColumna);
}
}
Dividimos presentación, promedios y búsqueda en métodos. Para simplificar, asumimos que la matriz y sus filas contienen datos.
Ampliación: filas irregulares
Java permite que cada fila tenga una longitud distinta:
int[][] registros = {
{3, 5},
{8, 2, 9},
{4}
};
No necesitamos profundizar ahora. La regla importante es recorrer cada fila con registros[fila].length en lugar de asumir un tamaño común.
Errores habituales
- Intercambiar fila y columna al acceder.
- Usar
matriz.lengthcomo número de columnas. - Escribir
<=en alguno de los recorridos. - Reiniciar un acumulador en el nivel incorrecto.
- Suponer que todas las filas miden lo mismo sin haberlo garantizado.
- Acceder a
matriz[0]sin comprobar que existe alguna fila.
Ejercicio: ventas por tienda
Una matriz contiene las ventas de dos tiendas durante tres meses:
Tienda 0: 12, 15, 10
Tienda 1: 9, 18, 14
Muestra el total de cada tienda, el total de cada mes y la celda con la venta máxima.
Resultados: tiendas 37 y 41; meses 21, 33 y 24; máxima 18 en fila 1, columna 1.
Solución razonada
public class ResumenVentas {
public static void main(String[] args) {
int[][] ventas = {
{12, 15, 10},
{9, 18, 14}
};
for (int fila = 0; fila < ventas.length; fila++) {
int totalTienda = 0;
for (int columna = 0; columna < ventas[fila].length; columna++) {
totalTienda += ventas[fila][columna];
}
System.out.println("Tienda " + fila + ": " + totalTienda);
}
for (int columna = 0; columna < ventas[0].length; columna++) {
int totalMes = 0;
for (int fila = 0; fila < ventas.length; fila++) {
totalMes += ventas[fila][columna];
}
System.out.println("Mes " + columna + ": " + totalMes);
}
int maximo = ventas[0][0];
int filaMaximo = 0;
int columnaMaximo = 0;
for (int fila = 0; fila < ventas.length; fila++) {
for (int columna = 0; columna < ventas[fila].length; columna++) {
if (ventas[fila][columna] > maximo) {
maximo = ventas[fila][columna];
filaMaximo = fila;
columnaMaximo = columna;
}
}
}
System.out.println("Máxima: " + maximo + " en "
+ filaMaximo + ", " + columnaMaximo);
}
}
Cambiar el orden de los bucles nos permite agrupar por tienda o por mes. Ya contamos con todas las herramientas conceptuales de Java 1; ahora toca combinarlas en problemas completos.