Skip to content

1 Arrays unidimensionales

Introducción

Los tipos de datos que conocemos hasta ahora no permiten solucionar problemas que requieren gestionar muchos datos a la vez. Por ejemplo, imaginemos que deseamos almacenar las notas de una clase de 25 alumnos, para ello, con lo que conocemos hasta ahora, no habrá más remedio que declarar 25 variables. Eso es tremendamente pesado de programar. Manejar esos datos significaría estar continuamente manejando 25 variables. Por ello, en casi todos los lenguajes se pueden agrupar una serie de variables del mismo tipo en una misma estructura que comúnmente se conoce como array. Esa estructura permite referirnos a todos los elementos, pero también nos permite acceder individualmente a cada uno de ellos.

Los arrays son una colección de datos del mismo tipo al que se le pone un nombre. Para acceder a un dato individual de la colección hay que utilizar su posición. La posición es un número entero, normalmente se le llama índice. Hay que tener en cuenta que en los arrays el primer elemento tiene como índice el número cero, el segundo el uno y así sucesivamente.

Un array unidimensional es aquel que tiene una única dimensión, es decir, un único índice. También se le suele llamar vector

Declaración

Existen dos formas de declarar un array unidimensional:

  • tipo nombre_array[];
  • tipo[] nombre_array;

tipo declara el tipo de elemento del array, es decir, el tipo de datos de cada elemento que comprende el array. Dicho tipo de datos puede ser un tipo primitivo o un objeto.

Esta declaración le dice al compilador que dicha variable va a contener un array con elementos de dicho tipo pero todavía no se reserva espacio en la memoria RAM ya que no se conoce el tamaño del mismo.

Creación

Se realiza con el operador new, que es el que realmente crea el array indicando un tamaño. Cuando se usa new es cuando se reserva el espacio necesario en memoria para el array.

Se crea un array de la siguiente manera: nombre_array = new tipo[tamaño];

Ejemplo:

int[] grades; //(1)!
grades = new int[3]; //(2)!
  1. Declaración del array de enteros llamado grades
  2. Creación del array grades reservando en memoria espacio para 3 enteros

Se puede realizar lo mismo en una única línea de código:

int[] grades = new int[3];

Referencia a los elementos del array

Para referencias los elementos del array se utiliza el índice de los mismos entre corchetes:

  • grades[0]: es el primer elemento del array, es decir, la primera nota.
  • grades[1]: es el segundo elemento del array, es decir, la segunda nota.
  • grades[2]: es el tercer elemento del array, es decir, la tercera nota.

Asignación de valores

Se puede asignar valores a los elementos del array utilizando el signo =:

grades[2] = 8; // Se le asigna un 8 a la tercera nota.

También se pueden asignar valores a todos los elementos del array utilizando literales array:

int[] grades = new int[] {8, 7, 9};

No es necesario escribir new int[] en las últimas versiones de Java:

int[] grades = {8, 7, 9}; 

En este caso, se está asignando un 8 a la primera nota, un 7 a la segunda nota y un 9 a la tercera.

El atributo length

Los arrays poseen el atributo length que contiene el tamaño del array:

System.out.println(grades.length); // 3

Utilizando el bucle for

La ventaja de usar arrays es que gracias a un simple bucle for se pueden recorrer fácilmente todos los elementos de un array:

public class ArrayFor {
    public void show(){
        int[] grades = {8, 7, 9};

        for(int i = 0; i < grades.length; i++){
            System.out.printf("Nota del índice %d: %d\n", i, grades[i]);
        }
    }

    public static void main(String[] args) {
        new ArrayFor().show();
    }
}

¡CUIDADO!

Los índices del array van desde el 0 hasta length-1. Si un array es de tamaño 3, sus índices son 0, 1 y 2. Por eso en la condición del for se debe iterar mientras i sea menor que array.length, y no menor o igual, de esta forma toma como último índice el length-1. Si pusiéramos la condición menor o igual, nos lanzaría la excepción ArrayIndexOutOfBoundsException ya que estaríamos accediendo al array con el índice 3, el cual es un índice no válido.

for(int i = 0; i <= grades.length; i++){ // Lanza ArrayIndexOutOfBoundsException
    //...
}

También se pueden utilizar con los arrays los bucles for-each:

public class ArraysForEach {
    public void show(){
        int[] grades = {8, 7, 9};

        for (int grade : grades) {
            System.out.printf("Nota: %d\n", grade);
        }
    }

    public static void main(String[] args) {
        new ArraysForEach().show();
    }
}
Ejercicio 1

Dado un array de 10 números, realiza la suma de los números pares.

Método split

Las clases String y Pattern poseen el método split que divide una cadena en subcadenas en función de una expresión regular y devuelve un array con las subcadenas restantes.

public class Split {
    public void show(){
        String string = "Esto:es:una:cadena:dividida:por:split";
        String[] stringArray = string.split(":");
        System.out.println(Arrays.toString(stringArray)); // [Esto, es, una, cadena, dividida, por, split]
    }

    public static void main(String[] args) {
        new Split().show();
    }
}

Tip

Fíjense en el método estático toString de la clase Arrays. Devuelve una cadena con los elementos del array entre corchetes y separados por comas.

Ejercicio 2

Realiza un programa que solicite al usuario una frase. Transforma esa frase en un array que cuyo valores sean las palabras de la frase, luego recorre el array.

Los arrays se implementan como objetos

En Java, los arrays se implementan como objetos. Una de las ventajas que tiene esto es que los arrays que pierden la referencia pueden ser recolectados. (Ver el apartado referencias del tema 4 Programación Orientada a Objetos)

En la perspectiva de Java, un array es una referencia a una serie de valores que se almacenan en la memoria. El operador new en realidad lo que hace es devolver dicha referencia para poder leer y escribir esos valores.

Veamos el efecto del uso operador new en los arrays y cómo afectan en la memoria:

Figura 1 - Referencia arrays

Figura 1 - Referencia arrays

Vemos como el anterior array se ha quedado sin referencia y se marca como elegible para el recolector de basura.

¿Qué puede contener un array?

El array puede contener objetos o tipos de datos primitivos. En el caso de los tipos de datos primitivos, los valores reales se almacenan en ubicaciones de memoria contigua. En el caso de los objetos de una clase, los objetos reales se almacenan en heap.

Arrays de tipos primitivos

  • Crear una variable de tipo array sólo crea una referencia:

    int[] a;
    

    Figura 2 - Declaración de arrays de tipo primitivos
    Figura 2 - Declaración de arrays de tipo primitivos

  • El espacio en memoria para el array se crea con new. Cuando se trata de un array de un tipo primitivo, se crean los elementos del array y se inicializan sus valores por defecto:

    a = new int[5];
    

    Figura 3 - Inicialización de arrays de tipo primitivos
    Figura 3 - Inicialización de arrays de tipo primitivos

Array de objetos

  • Crear una variable de tipo array de objetos sólo crea la referencia:

    Complejo[] a;
    

    Figura 4 - Declaración de arrays de objetos
    Figura 4 - Declaración de arrays de objetos

  • Con new se reserva el espacio para el array de referencias pero no los objetos a los que apuntarán esas referencias. Las referencias se inicializan a su valor por defecto (null):

    a = new Complejo[4];
    

    Figura 5 - Inicialización de arrays de objetos
    Figura 5 - Inicialización de arrays de objetos

  • Los objetos hay que crearlos posteriormente:

    Figura 6 - Creación de objetos de objetos
    Figura 6 - Creación de objetos de objetos

Asignación de arrays

Como en Java los arrays son objetos, la asignación se realiza como los objetos (Ver el apartado referencias del tema 4 Programación Orientada a Objetos)

Un array se puede asignar a otro array (si son del mismo tipo). La asignación solo copia referencias, es decir, la dirección de memoria. Por lo tanto, ambos arrays apuntarán al mismo sitio:

int[] a;
int[] b = {3, 4, 5, 6, 7, 8};

a = b;

Figura 7 - Referencia array

Figura 7 - Referencia array

Esta asignación provoca que cualquier cambio en a también cambie el array b ya que de hecho, son el mismo array:

public class Assignment {
    public void show(){
        int[] a;
        int[] b = {3, 4, 5, 6, 7, 8};
        a = b;

        System.out.println(Arrays.toString(b)); // [3, 4, 5, 6, 7, 8]
        a[0] = 1;
        System.out.println(Arrays.toString(b)); // [1, 4, 5, 6, 7, 8]
    }

    public static void main(String[] args) {
        new Assignment().show();
    }
}
Ejercicio 3

Realiza un programa que contenga un método que calcule los n primeros múltiplos de un número. Luego realiza otro método donde calcule la mitad de esos números. NO SE PUEDEN UTILIZAR PARÁMETROS DE TIPO ARRAY

Comparación de arrays

Como en Java los arrays son objetos, la comparación se realiza como los objetos (Ver el apartado referencias del tema 4 Programación Orientada a Objetos).

El operador de igualdad == cuando se utiliza con arrays, no compara el contenido de los arrays sino sus direcciones de memoria o referencias, es decir, si apuntan al mismo array. Lo mismo ocurre con el método equals de los arrays, que compara las direcciones de memoria. Si queremos comparar el contenido de los arrays, tendremos que utilizar el método estático equals de la clase Arrays.

public class Comparison {
    public void show(){
        int[] array1;
        int[] array2 = {3, 4, 5, 6, 7, 8};
        int[] array3 = {3, 4, 5, 6, 7, 8};
        array1 = array2;

        System.out.println(array1 == array2); //(1)!
        System.out.println(array2 == array3); //(2)!
        System.out.println(array1.equals(array2)); //(3)!
        System.out.println(array2.equals(array3)); //(4)!
        System.out.println(Arrays.equals(array1, array2)); //(5)!
        System.out.println(Arrays.equals(array2, array3)); //(6)!
    }

    public static void main(String[] args) {
        new Comparison().show();
    }
}
  1. true porque apuntan al mismo array
  2. false porque no apuntan al mismo array
  3. true porque apuntan al mismo array
  4. false porque apuntan al mismo array
  5. true porque el contenido es el mismo ya que apuntan al mismo array
  6. true porque el contenido es el mismo

Arrays como parámetros

Al igual que las variables, también podemos pasar arrays a los métodos, es decir, se pueden definir parámetros del tipo array. En la llamada al método, lo que el método recibe como argumento es la dirección de memoria del array, por lo que si el método modifica el array, el array del método que efectúa la llamada también se ve afectado por dichos cambios.

public class ArraysAsParameters {
    public void show(){
        int[] array = {3, 4, 5, 6, 7, 8};
        System.out.println(Arrays.toString(array)); // [3, 4, 5, 6, 7, 8]
        method(array);
        System.out.println(Arrays.toString(array)); // [6, 8, 10, 12, 14, 16]
    }

    public void method(int[] array){
        for (int i = 0; i < array.length; i++) {
            array[i] *= 2;
        }
    }
    public static void main(String[] args) {
        new ArraysAsParameters().show();
    }
}
Ejercicio 4

Realiza un aplicación que contenga un método que reciba un array de cadenas y una palabra. El método localizará dicha palabra en el array, y devolverá true en caso de encontrarla, y false en cualquier otro caso.

Cómo retornar un array

Un método también puede devolver un array, en cuyo caso, lo que retorna es la dirección de dicho array.

public class ReturningAnArray {
    public void show(){
        int[] a;
        a = method();
        System.out.println(Arrays.toString(a)); // [3, 4, 5, 6, 7, 8]
    }

    public int[] method(){
        return new int[]{3, 4, 5, 6, 7, 8};
    }

    public static void main(String[] args) {
        new ReturningAnArray().show();
    }
}

En este caso, el main define una variable a de tipo array de enteros pero no hace el new del array, sino que recibe la dirección de memoria que le devuelve el método method. Sin embargo, el método method sí que hace el new del array porque su responsabilidad es crear el array, darle valores y devolverlo.

Ejercicio 5

Realiza un programa con un método que dado un número positivo, devuelva sus divisores.

Excepción ArrayIndexOutOfBoundsException

Cuando se intenta acceder a un elemento del array que no existe, Java nos lanza una excepción ArrayIndexOutOfBoundsException. El programador no debe capturar con un try-catch la excepción sino que debe corregir el error de programación que ha producido dicha excepción. Veamos un ejemplo:

public class ArrayIndexOutOfBoundsException1 {
    public void show(){
        int[] grades = {8, 7, 9};

        for (int i = 0; i <= grades.length; i++) {
            System.out.printf("Nota en el índice %d: %d\n", i, grades[i]);
        }
    }

    public static void main(String[] args) {
        new ArrayIndexOutOfBoundsException1().show();
    }
}

Como vemos en el ejemplo, al usar <=, se lanzará una excepción al intentar acceder al valor de la posición grades[3], que es el valor de grades.length, que es inexistente. No se debe usar un try-catch para manejar este error, sino que el programador debe corregir el error.