CodeGym /Cursos /JAVA 25 SELF /Operaciones básicas con arrays unidimensionales

Operaciones básicas con arrays unidimensionales

JAVA 25 SELF
Nivel 7 , Lección 2
Disponible

1. Array de tipo String

Y, brevemente, me gustaría hablar del array de tipo String.

Como ya dijimos, un array puede ser de cualquier tipo. Eso significa que se puede crear un array de tipo String. Así se vería el código si necesitáramos escribir un programa que «introduce por teclado 10 cadenas y las muestra en pantalla en orden inverso».

String[] array = new String[10];	// Creamos un objeto array de 10 elementos
for (int i = 0; i < 10; i++)		// Bucle de 0 a 9
{
   array[i] = console.nextLine();	// Leemos una línea del teclado y la guardamos en la celda del array
}
for (int i = 9; i >= 0; i--)		// Bucle de 9 a 0
{
    System.out.println(array[i]);	// Imprimimos en pantalla la celda correspondiente del array
}

¡El código prácticamente no cambió! Solo hubo que sustituir el tipo int por String al crear el array. Por lo demás, ¡todo es exactamente igual!

Introducción a null

He aquí un acertijo — ¿qué contienen las celdas de cada uno de estos arrays justo después de crearlos?

int[] numbers = new int[10];
String[] strings = new String[10];
User[] users = new User[10];

Si lo piensas, lo más probable es que las celdas de numbers contengan 0. Correcto.

Entonces, por la misma lógica, las celdas de strings deberían estar rellenas con cadenas vacías — "". Supongamos.

¿Y con qué están rellenas las celdas del array users? ¿Con User «vacíos»?

Aquí está el truco: no todos los tipos de datos tienen un «valor por defecto». Por eso los creadores de Java idearon una constante especial — null. null es una referencia vacía. Cuando se crea una variable de un tipo-objeto, su valor inicial es null: referencia a nada, ausencia de referencia.

String name; 	// name contiene null
name = "Alex";  // name contiene una referencia al objeto/cadena "Alex"
name = null; 	// name contiene null

Trabajar con null

No se pueden invocar métodos de un objeto si su referencia es null — ¡el objeto no existe! En este código, el programa terminará con un error:

String name; 	// name contiene null
String upperName = name.toUpperCase(); // Se producirá un NullPointerException: name == null

En cuanto a nuestro «acertijo», la respuesta sería la siguiente:

int[] numbers = new int[10];		// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
String[] strings = new String[10];  // {null, null, null, null, null, null, null, null, null, null}
User[] users = new User[10];		// {null, null, null, null, null, null, null, null, null, null}

Solo los tipos primitivos tienen un «valor por defecto». Todos los demás tipos tienen por defecto el valor null. El valor inicial de String no es la cadena vacía. Así es la vida.

2. Array de tipo String en memoria

Imagen 1. Cómo se ubica en memoria un objeto String:

Array de tipo String en memoria

Fíjate en que el texto de la cadena no se guarda directamente en la variable: para él se reserva un bloque de memoria aparte. Y en la variable de tipo String se guarda la dirección (referencia) al objeto con el texto.

Imagen 2. Cómo se ubica en memoria un array de enteros:

Array int en memoria

También has visto esta imagen.

Imagen 3. Cómo se ubica en memoria un array de cadenas:

Cómo se ubica en memoria un array de String

A la izquierda vemos la variable-array de tipo String[] (guarda la dirección del objeto-array).

En el centro — el objeto-array de tipo String.

Y a la derecha — los objetos-cadena que almacenan distintos textos.

En las celdas del objeto-array de tipo String no se guardan las cadenas (los textos) en sí, sino sus direcciones (referencias). Exactamente igual que en las variables de tipo String se guardan direcciones de cadenas (texto).

3. Inicialización rápida de arrays en Java

Los arrays son muy útiles, por eso los desarrolladores de Java intentaron facilitar al máximo el trabajo con ellos. Y lo primero que hicieron fue simplificar la inicialización del array, es decir, establecer valores iniciales.

Muy a menudo, además de los datos que el programa lee de alguna parte, también necesita sus propios datos internos. Por ejemplo, necesitamos almacenar en un array los días de todos los meses. ¿Cómo podría ser este código?

int[] months = new int[12];
months[0] = 31; // enero
months[1] = 28; // febrero
months[2] = 31; // marzo
months[3] = 30; // abril
months[4] = 31; // mayo
months[5] = 30; // junio
months[6] = 31; // julio
months[7] = 31; // agosto
months[8] = 30; // septiembre
months[9] = 31; // octubre
months[10] = 30; // noviembre
months[11] = 31; // diciembre

Pero hay una forma de escribirlo más corto — gracias a los creadores de Java:

// días de los meses del año
int[] months = new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

¡Se pueden enumerar simplemente, separados por comas, todos los valores del array!

Resulta que el compilador puede determinar el tipo del contenedor (objeto-array) basándose en el tipo de la variable-array. Y para determinar la longitud del array — contar los elementos escritos entre llaves.

Por eso este código se puede escribir aún más corto:

// días de los meses del año
int[] months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

¿No es bonito? 🙂 A esta notación se le llama «inicialización rápida de un array». Por cierto, funciona no solo para el tipo int...

// nombres de los meses del año
String[] months = { "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" };

4. Bucle for-each

Recorrer todos los elementos de un array es una operación tan común que para ello se inventó un bucle especialfor-each. Se escribe así:

for (int score : scores)
{
    System.out.println("Puntos: " + score);
}
Recorrer los elementos de un array con for-each

Aquí el bucle recorre los elementos por sí mismo — sin índice manual. Pero no se pueden cambiar los elementos directamente (en la variable del bucle solo se guarda una copia del valor); eso sí, resulta muy cómodo simplemente «recorrer» el array.

El compilador transformará el código del bucle for-each en el código siguiente:

for (int i = 0; i < scores.length; i++)
{
    int score = scores[i];
    System.out.println("Puntos: " + score);
}
Cómo funciona for-each «por dentro»

Así que no hay magia. Ahora se entiende por qué no puedes cambiar los elementos del array a través de la variable score.

Escribamos otro ejemplo: calculemos la suma de todos los puntos.

int sum = 0;
for (int score : scores)
{
    sum += score;
}
System.out.println("Suma de todos los puntos: " + sum);
Cálculo de la suma de los valores del array con for-each

¿Cuándo usar cada tipo de bucle?

  • Si necesitas el índice o modificar elementos — usa el bucle for.
  • Si solo necesitas iterar por los valores — for-each es más rápido y limpio.

5. Modificar elementos de un array

¿Y si necesitamos aumentar cada nota en 1 punto (por ejemplo, por buen comportamiento)? Aquí hace falta un for clásico con índice, ya que solo así podemos cambiar los valores del array.

Ejemplo: aumentar cada elemento en 1

for (int i = 0; i < grades.length; i++) {
    grades[i] = grades[i] + 1;
}

Después de ejecutar este código, el array grades tendrá nuevos valores.

¿Por qué no se puede hacer con for-each?

for (int grade : grades) {
    grade = grade + 1; // ¡No funciona!
}

Este código no cambiará el array porque grade es una copia del valor del array, no una referencia al elemento en sí.

6. Cálculos basados en arrays

Los arrays se usan a menudo para cálculos: suma, media, máximo, mínimo, etc.

Ejemplo: suma de todos los elementos del array

int sum = 0;
for (int i = 0; i < grades.length; i++) {
    sum += grades[i]; // lo mismo que sum = sum + grades[i];
}
System.out.println("Suma de las notas: " + sum);

Ejemplo: búsqueda del valor máximo

int max = grades[0]; // empezamos con el primer elemento
for (int i = 1; i < grades.length; i++) {
    if (grades[i] > max) {
        max = grades[i];
    }
}
System.out.println("Nota máxima: " + max);

Ejemplo: búsqueda del valor mínimo

int min = grades[0]; // empezamos con el primer elemento
for (int i = 1; i < grades.length; i++) {
    if (grades[i] < min) {
        min = grades[i];
    }
}
System.out.println("Nota mínima: " + min);

Ejemplo: cálculo de la media aritmética

int sum = 0;
for (int i = 0; i < grades.length; i++) {
    sum += grades[i];
}
double average = (double) sum / grades.length; // ¡hay que convertir a double!
System.out.println("Nota media: " + average);

Atención: para obtener un número no entero, hay que convertir explícitamente la suma a tipo double antes de dividir.

7. Tareas prácticas

Entrada de un array por teclado

A menudo es necesario rellenar un array con valores que introduce el usuario. Para ello usamos la clase Scanner y un bucle.

Scanner console = new Scanner(System.in);

int n = 5; // tamaño del array
int[] numbers = new int[n];

System.out.println("Introduce " + n + " números:");
for (int i = 0; i < n; i++) {
    numbers[i] = console.nextInt();
}

System.out.println("Has introducido:");
for (int i = 0; i < n; i++) {
    System.out.println(numbers[i]);
}

Imprimir un array en orden inverso

A veces hay que imprimir los elementos de un array desde el final (por ejemplo, para saber quién entró el último en la habitación).

for (int i = grades.length - 1; i >= 0; i--) {
    System.out.println("Nota n.º " + (i + 1) + ": " + grades[i]);
}

8. Errores típicos al trabajar con arrays unidimensionales

Error n.º 1: salir de los límites del array

El problema más común es intentar acceder a un elemento inexistente. En Java esto provoca la excepción ArrayIndexOutOfBoundsException. Recuerda: el último índice válido es arr.length - 1.

int[] arr = new int[5];
System.out.println(arr[5]); // ¡Error! Índices de 0 a 4.

Error n.º 2: olvidar inicializar el array

Se declaró la variable, pero no se creó el array:

int[] arr;
arr[0] = 5; // ¡Error! El array no está creado.

Es imprescindible crear el array con new:

arr = new int[10];

Error n.º 3: intentar modificar elementos del array con for-each

En el bucle for-each la variable es una copia del valor, no una referencia al elemento:

for (int x : arr) {
    x = 100; // ¡No modifica el array!
}

Para modificar valores, usa un for con índice.

Error n.º 4: uso incorrecto de la longitud del array

A veces se confunde la longitud del array con el último índice:

for (int i = 0; i <= arr.length; i++) { // ¡Error! Debe ser i < arr.length
    // ...
}

Este código provocará un acceso fuera de los límites.

Error n.º 5: conversión implícita de tipos

Si el array es de tipo int, no se le puede asignar directamente un valor de tipo double:

int[] arr = new int[3];
arr[0] = 3.14; // ¡Error! 3.14 — es double.
1
Tarea
JAVA 25 SELF, nivel 7, lección 2
Bloqueada
Configuración inicial de la tabla de puntuaciones 🚀
Configuración inicial de la tabla de puntuaciones 🚀
1
Tarea
JAVA 25 SELF, nivel 7, lección 2
Bloqueada
Colección de películas favoritas en orden inverso 🎞️
Colección de películas favoritas en orden inverso 🎞️
1
Tarea
JAVA 25 SELF, nivel 7, lección 2
Bloqueada
Cálculo del total de compras en el carrito 🛍️
Cálculo del total de compras en el carrito 🛍️
1
Tarea
JAVA 25 SELF, nivel 7, lección 2
Bloqueada
Determinación de la temperatura máxima del día 🌡️
Determinación de la temperatura máxima del día 🌡️
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION