Explorando los Arreglos Bidimensionales en Java
Los arreglos bidimensionales son una estructura de datos fundamental en la programación en Java. En este artículo se exploran los conceptos básicos de esta estructura de datos, incluyendo cómo crear y manipular arreglos bidimensionales en Java. También se discutirán las diferentes maneras en que se pueden utilizar los arreglos bidimensionales, desde la representación de matrices hasta la creación de juegos.
Además, se explorarán algunas técnicas útiles para trabajar con arreglos bidimensionales, como la iteración a través de los arreglos y el uso de métodos para acceder y modificar elementos.
Si estás buscando información sobre arreglos unidimensionales, puedes leer mi artículo sobre arreglos unidimensionales en Java. O tal vez quieras saber sobre los arreglos dinámicos, para eso puedes referirte al artículo sobre arreglos dinámicos en Java.
¿Qué es un arreglo bidimensional?
Un arreglo bidimensional es una estructura de datos que almacena múltiples elementos, organizados en renglones y columnas, es decir, de forma tabular. Cada elemento en el arreglo se puede acceder utilizando 2 índices – uno que representa en cuál renglón se encuentra el elemento y otro que representa en cuál columna.
Estos arreglos pueden ser usados para almacenar datos multidimensionales, como coordenadas, textos de diferentes índoles, o datos de problemas matemáticos.
Los arreglos bidimensionales (arreglos de dos dimensiones) también son conocidos como matrices, y son un subconjunto de los arreglos multidimensionales, dado que también existen arreglos de 3 dimensiones, 4 dimensiones, y más.
¿Cómo se declara un arreglo bidimensional en Java?
Para declarar un arreglo bidimensional en Java, debes seguir la sintaxis:
tipo_dato[][] nombre_arreglo = new tipo_dato[numero_renglones][numero_columnas];
Donde,
tipo_dato
es el tipo de dato que deberán tener los elementos del arreglo, puede ser un tipo de dato primitivo (comoint
ofloat
) o un tipo de objeto (comoString
)nombre_arreglo
es el nombre con el que se identifica al arreglonumero_renglones
es el número de renglones del arreglonumero_columnas
es el número de columnas del arreglo
Ejemplos de arreglos bidimensionales en Java
A continuación un ejemplo de como se declara un arreglo bidimensional con elementos de tipo primitivo:
int[][] numerosEnteros = new int[2][3];
En el ejemplo anterior se declara un arreglo bidimensional llamado numerosEnteros
,
que será de 2 renglones y 3 columnas, y que deberá contener elementos de tipo entero (int
).
Puedes observar en la imagen anterior que aunque no inicializamos el arreglo, Java inicializó todos los elementos con ceros. Este es el valor por defecto que Java usa para las variables de tipo entero (int).
A continuación un ejemplo de como se declara un arreglo bidimensional con elementos de tipo Objeto:
String[][] cadenas = new String[3][5];
En el ejemplo anterior se declara un arreglo bidimensional llamado cadenas
,
que será de 3 renglones y 5 columnas, y que deberá contener elementos de tipo String
.
En la imagen anterior podrás deducir que Java inicializa los elementos con null
cuando nosotros no hemos
asignado ningún valor a un arreglo de tipo objeto.
Declarando arreglos bidimensionales con diferente número de columnas por renglón
También es posible declarar arreglos bidimensionales en Java con un número de columnas distinto por renglón. Para ello debes usar la siguiente sintaxis,
tipo_dato[][] nombre_arreglo = tipo_dato[numero_renglones][];
Como podrás notar, el número de columnas se omite, y solo se especifica el número de renglones. De esa forma, se pueden asignar tamaños de columnas diferentes en cada renglón.
¿Cómo se usan los arreglos bidimensionales?
Los arreglos bidimensionales se usan por medio de coordenadas, ya sea para guardar elementos en el arreglo, o para obtener los elementos que hayan sido previamente almacenados. Todo esto es con la finalidad de poder manipular datos que pueden representarse en matrices, es decir, arreglos de dos dimensiones o arreglos bidimensionales.
Además, hay varias operaciones que pueden realizarse con los arreglos bidimensionales, como ordenarlos de forma ascendente o descendente, buscar un elemento dentro del arreglo, entre otras.
En las siguientes subsecciones exploraremos un poco más a detalle los usos más comunes de los arreglos bidimensionales.
¿Cómo llenar un arreglo bidimensional en Java?
Para llenar un arreglo bidimensional se utiliza la siguiente sintaxis:
nombre_arreglo[indice_renglon][indice_columna] = elemento;
Donde nombre_arreglo
es el identificador del arreglo; indice_renglon
es un número entero que identifica
el número del renglón donde deberá ir el elemento, empezando en 0
;
indice_columna
es un número entero que identifica el número de la columna donde deberá ir el elemento,
empezando en 0
; y elemento
es el elemento que queremos guardar en cierta posición del arreglo,
y este debe ser del mismo tipo de dato con el que se declaró el arreglo.
Por ejemplo, si tuviéramos el siguiente arreglo bidimensional,
String[][] nombres = new String[2][2];
Y queremos llenarlo con nombres y apellidos, sabemos que el arreglo bidimensional que definimos tiene capacidad para 2 nombres (con sus respectivos apellidos), porque tiene 2 renglones y 2 columnas, una columna para el nombre y una columna para el apellido.
Vamos a llenar el primer renglón de nuestro arreglo bidimensional,
// El primer nombre va en el primer renglón (índice 0) y la primer columna (índice 0)
nombres[0][0] = "Arturo";
// El primer apellido va en el primer renglón (índice 0) y la segunda columna (índice 1)
nombres[0][1] = "Parra";
Y en la siguiente imagen se muestra el estado del arreglo después de ejecutar las instrucciones anteriores.
Como no hemos asignado nada en el segundo renglón, aún tenemos los valores por defecto con los que Java
inicializó el arreglo, que en este caso es null
porque el arreglo es de tipo String,
por ende, es de tipo Objeto, y sabemos que Java inicializa los elementos de tipo Objeto
con el valor de null
.
Ahora llenemos el segundo renglón,
// El segundo nombre va en el segundo renglón (índice 1) y la primer columna (índice 0)
nombres[1][0] = "Enrique";
// El segundo apellido va en el segundo renglón (índice 1) y la segunda columna (índice 1)
nombres[1][1] = "Sánchez";
Y nuestro arreglo bidimensional quedaría como en la siguiente imagen,
También es posible declarar e inicializar un arreglo bidimensional en Java al mismo tiempo, por medio de la siguiente sintaxis,
tipo_dato[][] nombre_arreglo = {
{e1_1, e1_2, ...e1_M},
{e2_1, e2_2, ...e2_M},
.
.
.
{eN_1, eN_2, ...eN_M}
};
Donde,
- tipo_dato es el tipo de dato que deberán tener los elementos del arreglo
- nombre_arreglo es el identificador del arreglo
- N es el número de renglones
- M es el número de columnas
- e1_1 a _e1_M son los elementos del primer renglón
- e2_1 a _e2_M son los elementos del segundo renglón
- eN_1 a _eN_M son los elementos del último renglón
Leyendo elementos de un arreglo bidimensional en Java
Para leer un elemento de un arreglo bidimensional en Java, debes especificar las coordenadas del elemento que quieres obtener, con la siguiente sintaxis,
nombre_arreglo[ren][col];
Donde,
- nombre_arreglo es el identificador del arreglo
- ren es el índice del renglón donde se encuentra el elemento
- col es el índice de la columna donde se encuentra el elemento
Por ejemplo, dado el siguiente arreglo bidimensional que representa las comidas de 7 días de la semana,
String[][] comidas = {
{"Avena", "Cereal", "Huevo", "Yogur", "Fruta", "Pan tostado con aguacate", "Hotcakes"},
{"Pollo", "Sándwich", "Verduras", "Atún", "Bistec", "Champiñones", "Espagueti"},
{"Burritos de frijoles", "Quesadillas", "Estofado", "Picadillo", "Lasaña", "Ensalada con pollo", "Pizza"}
};
Y puede ser visualizado de la siguiente manera,
Donde cada columna es un día de la semana, es decir, la columna 0
representa el lunes,
la columna 1
representa el martes, y así sucesivamente; el primer renglón (índice 0
) es para desayunos;
el segundo renglón (índice 1) es para comidas; y el tercer renglón (índice 2) es para cenas.
Si queremos obtener la cena del jueves, lo haríamos de la siguiente manera,
String cenaMiercoles = comidas[2][3];
System.out.println("La cena del jueves es: " + cenaMiercoles);
El ejemplo anterior imprime “La cena del jueves es: Picadillo”, porque sabemos que
el tercer renglón contiene las cenas (índice 2)
y el jueves está representado en la cuarta columna (índice 3). Así que accedemos a los respectivos
índices en el arreglo bidimensional por medio de las “coordenadas” [2][3]
, luego asignamos el resultado a una variable de tipo String
llamada cenaMiercoles
, y finalmente procedemos a imprimirla en pantalla con
System.out.println...
Por supuesto que todo lo anterior funciona muy bien cuando conocemos exactamente los elementos que queremos acceder, pero ¿cómo le hacemos si queremos leer todos los elementos?. Claro que podríamos leer uno por uno manualmente, indicando las coordenadas de todos y cada uno de los elementos, pero no es una forma muy práctica de hacerlo. Para este tipo de operaciones es mejor utilizar un ciclo para recorrer el arreglo, como lo veremos en las siguientes secciones.
Recorriendo un arreglo bidimensional de forma horizontal (leyendo renglones)
Continuando con el ejemplo del arreglo bidimensional con las comidas de siete días de la semana,
digamos que solo nos interesa saber todos los almuerzos de la semana, como los almuerzos
se encuentran en el primer renglón, podríamos utilizar un ciclo for
para movernos
por todas las columnas del renglón ubicado en el índice 0
, de la siguiente forma,
System.out.println("Los almuerzos de toda la semana son:");
for (int i = 0; i < 7; i++) {
System.out.println( comidas[0][i] );
}
El código anterior demuestra que el índice que corresponde al renglón lo dejamos constante en 0
,
dado que sabemos que los almuerzos están en ese renglón, así que la variable de iteración i
es
la que utilizamos para el índice de la columna, y dadas las instrucciones que especificamos en el ciclo for
,
recorreremos todas las columnas del primer renglón, a continuación te explico cada instrucción del for
,
int i = 0;
- Inicializa la variable de iteración con0
i < 7;
- El ciclo se ejecuta mientras esta condición sea válida, o sea que la variable de iteración irá adquiriendo los valores desde0
hasta6
, que son precisamente los índices disponibles para todas las columnas (los 7 días de la semana)i++
- Incrementa la variable de iteración en 1, por cada ciclo que recorre.
La instrucción i < 7;
especifica el número de columnas manualmente, o sea el número 7
,
porque sabemos que nuestro arreglo bidimensional cuenta con siete columnas, pero no siempre
conocemos el número de columnas de antemano, por lo que tendríamos que determinar el tamaño
del renglón de alguna otra forma.
Afortunadamente, tanto los arreglos unidimensionales como multidimensionales en Java,
cuentan con una propiedad que guarda el tamaño de los mismos, me refiero a la propiedad length
.
Por ejemplo, si no supiéramos el número de columnas del arreglo comidas
,
podríamos utilizar la propiedad length
de cualquiera de los renglones,
y nuestro ciclo for
quedaría como sigue,
for (int i = 0; i < comidas[0].length; i++) {
System.out.println( comidas[0][i] );
}
Y lo que imprime el código anterior es,
Los almuerzos de toda la semana son:
Avena
Cereal
Huevo
Yogur
Fruta
Pan tostado
Hotcakes
La expresión comidas[0].length
obtiene el número de columnas del primer renglón,
o sea 7
, y como todos los renglones tienen el mismo número de columnas, también pudimos utilizar
comidas[1].length
o comidas[2].length
, pero como queremos recorrer el primer renglón,
tiene más sentido utilizar el índice 0
.
Y ya que vimos cómo recorrer un renglón en un arreglo bidimensional, ¿qué tal si demostramos cómo hacer lo correspondiente con las columnas?, veámoslo en la siguiente sección.
¿Cómo recorrer una columna en un arreglo bidimensional en Java?
Sigamos con nuestro arreglo bidimensional de las comidas de la semana de las secciones anteriores,
y supongamos que ahora queremos saber las comidas correspondientes al martes,
para eso debemos recorrer el arreglo de forma vertical, en particular la segunda columna,
con índice 1
.
A continuación una representación visual del arreglo de comidas, resaltando las comidas del martes (segunda columna, índice 1),
En el ciclo for
que utilizaremos para recorrer el arreglo,
ahora lo que queremos es dejar estático es el número de la segunda columna (índice 1),
y recorrer todos los renglones de esa misma columna.
System.out.println("Las comidas correspondientes al martes son: ");
for (int i = 0; i < 3; i++) {
System.out.println( comidas[i][1] );
}
Lo cual imprime en pantalla lo siguiente,
Las comidas correspondientes al martes son:
Cereal
Sándwich
Quesadillas
Al igual que en el caso de los renglones, aquí sabemos el número de renglones de nuestro arreglo bidimensional,
pero si no contáramos con ese dato, podríamos averiguarlo con la propiedad length
, de la siguiente manera,
for (int i = 0; i < comidas.length; i++) {
System.out.println( comidas[i][1] );
}
Cuando se invoca la propiedad length
en un arreglo bidimensional, sin utilizar ningún índice,
como lo hicimos con comidas.length
, lo que Java nos regresa es el número total de renglones,
que en este caso es 3
.
Para saber el número de columnas de un renglón en particular de un arreglo bidimensional en Java, se logra con la siguiente sintaxis,
nombre_arreglo[indice_renglon].length;
Por otro lado, si lo que se quiere es saber el número de renglones, se hace así,
nombre_arreglo.length;
Recorriendo un arreglo bidimensional completo
Tal vez quieras recorrer un arreglo bidimensional completamente, digamos que queremos imprimir en pantalla todas las comidas de la semana que almacenamos en el arreglo con el que trabajamos en las secciones anteriores.
Para ello, se combinan las técnicas para recorrer columnas y para recorrer renglones,
en un par de ciclos for
anidados, de la siguiente manera,
for (int col = 0; col < comidas[0].length; col++) {
String dia = switch(col) {
case 0 -> "Lunes";
case 1 -> "Martes";
case 2 -> "Miercoles";
case 3 -> "Jueves";
case 4 -> "Viernes";
case 5 -> "Sábado";
case 6 -> "Domingo";
default -> "";
};
System.out.println("\n\nLas comidas del " + dia + " son: \n\n");
for (int ren = 0; ren < comidas.length; ren++) {
String tipo = switch(ren) {
case 0 -> " El desayuno";
case 1 -> " La comida";
case 2 -> " La cena";
default -> "";
};
System.out.println( tipo + ": " + comidas[ren][col] );
}
}
En el código de aquí arriba utilizamos expresiones switch, que fueron introducidas en Java 12, las cuales permiten escribir instrucciones con
switch
de una forma más concisa, pero si utilizas una versión anterior de Java (no recomendado), puedes implementar el mismo código con unswitch
tradicional.
El código anterior nos daría el resultado siguiente (Se omiten resultados por brevedad),
Las comidas del Lunes son:
El desayuno: Avena
La comida: Pollo
La cena: Burritos de frijoles
Las comidas del Martes son:
El desayuno: Cereal
La comida: Sándwich
La cena: Quesadillas
.
.
.
En el primer ciclo,
for (int col = 0; col < comidas[0].length; col++)
recorremos las columnas del arreglo bidimensional, que controlamos con la variable de iteración col
,
la cual obtendrá los valores 0
a 6
, dada la condición col < comidas[0].length.
Y por cada columna se ejecutará un segundo ciclo,
for (int ren = 0; ren < comidas.length; ren++)
que nos permite iterar por todos los renglones de cada columna respectivamente,
por medio de la variable de iteración ren
, la cual obtendrá los valores 0
a 2
,
dada la condición ren < comidas.length.
Con esto, puedes darte una buena idea de como recorrer un arreglo bidimensional en Java.
¿Cómo buscar un elemento en un arreglo bidimensional en Java?
La manera más sencilla de buscar un elemento en un arreglo bidimensional, es por medio de una búsqueda secuencial que recorra todos los elementos del arreglo, y conforme se va recorriendo, utilizar una condición para comparar el valor que se está buscando con cada uno de los elementos del arreglo.
Dado el siguiente arreglo bidimensional de 3 por 6, donde cada renglón representa una liga de fútbol soccer, y en cada celda se almacena el nombre de un equipo,
String[][] equipos = {
{"La Liga", "FC Barcelona", "Real Madrid", "Atlético de Madrid", "Real Sociedad", "Valencia CF"},
{"Liga Premier", "Arsenal", "Chelsea", "Liverpool", "Manchester City", "Manchester United"},
{"Liga MX", "Pumas", "Tigres", "América", "Chivas", "Monterrey"}
};
Enseguida, una representación visual del arreglo bidimensional. Observa cómo la primera columna contiene los nombres de las ligas, y el resto de las columnas contienen los nombres de los equipos pertenecientes a las ligas.
A continuación, el código que utilizaremos para implementar una búsqueda secuencial, pasando el nombre de un equipo, e imprimiendo el nombre de la liga al que pertenece el equipo,
String equipoBuscado = "FC Barcelona";
String liga = "";
for (int ren = 0; ren < equipos.length; ren++) {
for (int col = 1; col < equipos[ren].length; col++) {
if ( equipos[ren][col].equals(equipoBuscado) ) {
liga = equipos[ren][0];
break;
}
}
if ( !liga.isEmpty() ) {
break;
}
}
if ( liga.isEmpty() ) {
System.out.println("El equipo " + equipoBuscado + " no se encontró.");
} else {
System.out.println("El equipo " + equipoBuscado + " pertenece a " + liga + ".");
}
El código anterior imprimiría El equipo FC Barcelona pertenece a La Liga.
Al igual que en la sección anterior, aquí utilizamos un par de for
anidados,
pero en esta ocasión lo hacemos de forma invertida, es decir, primero recorremos los renglones,
y por cada renglón recorremos las columnas.
El primer ciclo,
for (int ren = 0; ren < equipos.length; ren++)
nos permite iterar los renglones del arreglo bidimensional, gracias a la variable de iteración ren
,
que obtendrá los valores de 0
a 2
, dada la condición ren < equipos.length,
o hasta que se encuentre el equipo deseado.
Luego, por cada renglón ejecutamos otro ciclo,
for (int col = 1; col < equipos[ren].length; col++)
por medio del cual recorremos las columnas del renglón en curso, gracias a la variable de iteración col
,
que adquiere los valores desde 1
hasta 6
, dada la condición col < equipos[ren].length,
o hasta que se encuentre el equipo buscado.
Cabe hacer notar que en el segundo ciclo empezamos por el índice 1
, en lugar del índice 0
,
esto es porque sabemos que la primera columna (el primer elemento de cada renglón),
contiene el nombre de la liga correspondiente a ese renglón, y no tanto el nombre de un equipo,
por lo que es innecesario comparar el nombre de la liga con el equipo buscado.
Referencias Bibliográficas
Selikoff, S., Boyarsky, J. (2014). OCA: Oracle Certified Associate Java SE 8 Programmer I Study Guide: Exam 1Z0-808. Reino Unido: Wiley.