Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% encontró este documento útil (0 votos)
87 vistas51 páginas

Arreglos 2

Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1/ 51

Java – Estructuras de datos – 

Arreglos
Un arreglo (popularmente en inglés: array) es una estructura de datos con una capacidad pre-
definida en la cual se pueden almacenar datos del mismo tipo. Estos datos son almacenados en
forma secuencial en la memoria y ocupan una determinada cantidad de bytes según cual sea el
tipo de dato. La capacidad de un arreglo se declara desde el primer momento cuando este es
construido, y no puede cambiar en tiempo de ejecución. Cada dato almacenado es considerado un
elemento al cual se accede por un índice de posición (un número entero no negativo).

La siguiente imagen esquematiza un arreglo con una capacidad de diez elementos:

Como se puede observar a cada elemento le corresponde un índice, pero la numeración comienza
desde 0. Es decir que el quinto elemento en el arreglo seria accedido bajo el índice 4, y el décimo
último elemento seria accedido bajo el índice 9 lo que equivale a: Tamaño total – 1.

Dentro de la terminología los arreglos uni-dimensionales se conocen como vectores, y entre los
arreglos multi-dimensionales están los arreglos bi-dimensionales que se conocen como matrices.
También los hay de más dimensiones pero no son comúnmente requeridos.

A continuación veremos como trabajar con arreglos ya sean vectores o matrices.

Declaración y construcción

Para declarar un arreglo debemos especificar el tipo de dato y asignarle un nombre para su
posterior referencia:
tipo_de_dato[] nombre_arreglo;

Notar que sintácticamente también es valido usar los paréntesis rectos (corchetes “[]”) al final del
nombre:

tipo_de_dato nombre_arreglo[];

Pero esta practica esta desaprobada por convención.

Por lo tanto si queremos declarar un arreglo de números enteros escribimos:

1 ...
2 int[] arregloEnteros;
3 ...

El tipo de dato puede ser primitivo o un objeto:

char[] arregloCaracteres;
byte[] arregloBytes;
int[] arregloEnteros;
short[] arregloCortos;
long[] arregloLargos;
float[] arregloFlotantes;
double[] arregloDobles;
boolean[] arregloBooleanos;
String[] arregloStrings;
MiObjeto[] arregloMisObjetos;
Para construir un arreglo utilizamos new como lo hacemos para construir una instancia de una
clase, ya que un arreglo es también un objeto. Por ejemplo:
new tipo_de_dato[TAMAÑO];

Como lógicamente necesitaríamos una referencia hacia el arreglo, para poder tener un acceso
hacia el mismo, necesitamos declararlo para luego construirlo lo cual dependería de la situación o
necesidad. En un ámbito local para uso inmediato podríamos declarar y construir simultáneamente
lo que seria:

tipo_de_dato[] nombre_arreglo = new tipo_de_dato[TAMAÑO];

Ó en un ámbito global en el cual construiríamos recién en un momento posterior:

tipo_de_dato[] nombre_arreglo;
...
void algunMetodo() {
nombre_arreglo = new tipo_de_dato[TAMAÑO];
...
}
Por lo tanto si queremos declarar y construir un arreglo de diez números enteros podemos escribir
siguiendo las situaciones anteriores:

1 ...
2 int[] arregloEnteros = new int[10];
3 ...

Ó escribir:

1
...
2 int[] arregloEnteros;
3 ...
4 void algunMetodo() {
5     arregloEnteros = new int[10];
    ...
6 }
7 ...
8

La asignación de memoria para los elementos de un arreglo ocurre cuando construimos no cuando
lo declaramos.

Asignación de valores

Cuando construimos un arreglo todos sus elementos serán iniciados con el valor predeterminado
del tipo de dato. Los objetos siempre son null mientras que un dato primitivo como un int vale 0.
A continuación una tabla con los valores predeterminados para cada tipo de dato:
Tipo de dato Valor
byte 0
short 0
long 0
int 0
double 0.0
float 0.0
char /u0000
boolean false
Objeto null
En la mayoría de los casos a un arreglo le es asignado su contenido en tiempo de ejecución, por lo
tanto la operación de especificar sus valores se posterga para cuando sea necesario. Teniendo un
arreglo ya construido la sintaxis para asignar o modificar el valor de un elemento es:

nombre_arreglo[ÍNDICE] = nuevo_valor;

Donde el índice es la posición del elemento en el arreglo teniendo en cuenta que la numeración
comienza desde 0.

Si tenemos un arreglo de tres strings tal que:

1 ...
int[] arregloStrings = { "string1", "string2", "string3"
2 };
3 ...
Entonces para modificar el valor del segundo elemento, “string2” por “nuevo string!“, escribiríamos:
1 ...
2 arregloStrings[1] = "nuevo string!";
3 ...

También se pude declarar, construir y asignar valores en un arreglo simultáneamente logrando


tener los valores iniciados desde el principio a través de una sintaxis corta:

1 ...
int[] arregloStrings = { "uno", "dos", "tres", "cuatro", "cinco", "seis", "siete", "o
2 "nueve", "diez" };
3 ...
Lo que hacemos es que en cambio de usar new y establecer el tamaño para solo construirlo,
directamente asignamos los valores que tendrá el arreglo delimitándolos por llaves “{}” con lo cual
estamos construyendo y asignándole valores desde el principio, aunque estos podrían ser
modificados en otro momento. En este tipo de sintaxis el compilador deduce las dimensiones del
arreglo.
Nota: en varios ejemplos de este tutorial usaré la declaración, construcción y asignación
simultanea, simplemente por conveniencia.

Accediendo a los elementos

Acceder a los elementos de un arreglo es sencillo, solo tenemos que especificar el nombre de la
referencia del arreglo y el indice del elemento, la sintaxis es:
nombre_arreglo[ÍNDICE];

Si tenemos un arreglo de cuatro caracteres tal que:

1 ...
2 char[] arregloCaracteres = { 'a', 'b', 'c', 'd' };
3 ...

Entonces para obtener el valor del tercer elemento, la “c“, podríamos escribir:
1 ...
2 char caracter = arregloStrings[2];
3 ...

Veamos ahora un ejemplo en el que creamos un arreglo de diez números enteros e imprimimos
sus valores en pantalla:

1 class ArrayDemo1 {
2  
    public static void main(String[] args) {
3         //declaramos y construimos un arreglo con una capacidad de diez números
4 enteros
5         int[] arreglo;
6         arreglo = new int[10];
7  
8         //asignamos los valores para cada posición en el arreglo...
        arreglo[0] = 100;
9         arreglo[1] = 200;
10         arreglo[2] = 300;
11         arreglo[3] = 400;
12         arreglo[4] = 500;
13         arreglo[5] = 600;
        arreglo[6] = 700;
14         arreglo[7] = 800;
15         arreglo[8] = 900;
16         arreglo[9] = 1000;
17  
18         //imprimimos en pantalla el valor de cada elemento...
        System.out.println("Elemento en indice 0: " + arreglo[0]);
19         System.out.println("Elemento en indice 1: " + arreglo[1]);
20         System.out.println("Elemento en indice 2: " + arreglo[2]);
21         System.out.println("Elemento en indice 3: " + arreglo[3]);
22         System.out.println("Elemento en indice 4: " + arreglo[4]);
23         System.out.println("Elemento en indice 5: " + arreglo[5]);
        System.out.println("Elemento en indice 6: " + arreglo[6]);
24         System.out.println("Elemento en indice 7: " + arreglo[7]);
25         System.out.println("Elemento en indice 8: " + arreglo[8]);
26         System.out.println("Elemento en indice 9: " + arreglo[9]);
27     }
28 }
29
30
31
32

La salida:

Elemento en indice 0: 100


Elemento en indice 1: 200
Elemento en indice 2: 300
Elemento en indice 3: 400
Elemento en indice 4: 500
Elemento en indice 5: 600
Elemento en indice 6: 700
Elemento en indice 7: 800
Elemento en indice 8: 900
Elemento en indice 9: 1000
La variable length
La variable length nos permite obtener el tamaño del arreglo, es decir su longitud que nos dice la
cantidad de elementos que posee (sin importar si son objetos null). Es una variable de solo lectura
por lo cual no podemos modificarla, puede resultar muy útil por ejemplo para iterar sobre los
elementos del arreglo es decir recorrerlo con alguna estructura de control como el bucle for.
nombre_arreglo.length

Veamos el código anterior usando esta variable:

1 class ArrayDemo2 {
2  
    public static void main(String[] args) {
3
        //declaramos y construimos un arreglo con una capacidad de diez números
4 enteros
5         int[] arreglo;
6         arreglo = new int[10];
7  
8         //asignamos los valores para cada posición en el arreglo...
        arreglo[0] = 100;
9         arreglo[1] = 200;
10         arreglo[2] = 300;
11         arreglo[3] = 400;
12         arreglo[4] = 500;
13         arreglo[5] = 600;
        arreglo[6] = 700;
14         arreglo[7] = 800;
15         arreglo[8] = 900;
16         arreglo[9] = 1000;
17  
18         //imprimimos en pantalla el valor de cada elemento...
        for (int i = 0 ; i < arreglo.length ; i++) {
19             System.out.println("Elemento en indice " + i + ": " + arreglo[i]);
20         }
21     }
22 }
23
24
25

La salida seria igual que lo visto anteriormente, pero el código es más corto y versátil.

También podemos recorrer el arreglo con otras estructuras de control, por ejemplo en el código
anterior podríamos haber usado un bucle for-each y nos quedaría de la siguiente forma:
1 ...
2 //imprimimos en pantalla el valor de cada elemento...
3 for (int n : arreglo) {
4     System.out.println("Elemento: " + n);
}
5 ...
6

La salida seria:

Elemento: 100
Elemento: 200
Elemento: 300
Elemento: 400
Elemento: 500
Elemento: 600
Elemento: 700
Elemento: 800
Elemento: 900
Elemento: 1000
Como vemos con este bucle for-each se simplifica el recorrido pero sucede también que perdemos
el control sobre el índice y como consecuencia no podríamos realizar modificaciones en el arreglo
mientras estemos en el bucle.

Copiar un arreglo

Primero que nada hay que notar algo importante sobre el siguiente código:

1 ...
2 int[] arreglo1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
3 ...
4 int[] arreglo2 = arreglo1;
...
5
Aquí hay un error conceptual si creemos estar creando una copia del arreglo1. Lo que estamos
haciendo sobre la línea de código marcada es asignarle a arreglo2 el valor de la referencia que se
tiene sobre arreglo1, es decir estamos copiando la referencia no el objeto. Como resultado no
obtenemos dos arreglos iguales sino dos referencias iguales que refieren al mismo arreglo.

Para copiar desde un arreglo hacia otro podemos tomarnos el trabajo de crear un nuevo arreglo
con la misma capacidad y copiar los elementos uno a uno como se muestra a continuación:

1
...
2 int[] arreglo1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
3 ...
4 int[] arreglo2 = new int[arreglo1.length];
5 for (int i = 0 ; i < arreglo1.length ; i++) {
    arreglo2[i] = arreglo1[i];
6 }
7 ...
8
Pero en cambio de hacerlo manualmente, tenemos la clase de utilidades java.lang.System que
ya nos proporciona un método más eficiente para esta tarea: void arraycopy(Object src,
int srcPos, Object dest, int destPos, int length). Veamos algunos casos:
 Copiar todo el contenido de un arreglo en otro arreglo:
1 class ArrayDemo3 {
2  
    public static void main(String[] args) {
3         //declaramos y construimos un arreglo con una capacidad de diez números ente
4         int[] arreglo;
5         arreglo = new int[10];
6  
7         //asignamos los valores para cada posición en el arreglo...
8         arreglo[0] = 100;
        arreglo[1] = 200;
9         arreglo[2] = 300;
10         arreglo[3] = 400;
11         arreglo[4] = 500;
12         arreglo[5] = 600;
13         arreglo[6] = 700;
        arreglo[7] = 800;
14         arreglo[8] = 900;
15         arreglo[9] = 1000;
16  
17         //imprimimos en pantalla el valor de cada elemento en el primer arreglo...
18         for (int i = 0 ; i < arreglo.length ; i++) {
            System.out.println("Arreglo 1 - Elemento en indice " + i + ": " +
19 arreglo[i]);
20         }
21  
22         System.out.println();
23  
24         //declaramos y construimos un nuevo arreglo con la misma capacidad que el
25 arreglo anterior
        int[] arregloCopia;
26         arregloCopia = new int[10];
27
28
29  
        //copiamos el contenido del primer arreglo en el segundo arreglo
30         System.arraycopy(arreglo, 0, arregloCopia, 0, 10);
31
 
32         //imprimimos en pantalla el valor de cada elemento en el segundo arreglo...
33         for (int i = 0 ; i < arregloCopia.length ; i++) {
34             System.out.println("Arreglo 2 - Elemento en indice " + i + ": " +
35 arregloCopia[i]);
        }
36     }
37 }
38
39

La salida:

Arreglo 1 – Elemento en indice 0: 100


Arreglo 1 – Elemento en indice 1: 200
Arreglo 1 – Elemento en indice 2: 300
Arreglo 1 – Elemento en indice 3: 400
Arreglo 1 – Elemento en indice 4: 500
Arreglo 1 – Elemento en indice 5: 600
Arreglo 1 – Elemento en indice 6: 700
Arreglo 1 – Elemento en indice 7: 800
Arreglo 1 – Elemento en indice 8: 900
Arreglo 1 – Elemento en indice 9: 1000

Arreglo 2 – Elemento en indice 0: 100


Arreglo 2 – Elemento en indice 1: 200
Arreglo 2 – Elemento en indice 2: 300
Arreglo 2 – Elemento en indice 3: 400
Arreglo 2 – Elemento en indice 4: 500
Arreglo 2 – Elemento en indice 5: 600
Arreglo 2 – Elemento en indice 6: 700
Arreglo 2 – Elemento en indice 7: 800
Arreglo 2 – Elemento en indice 8: 900
Arreglo 2 – Elemento en indice 9: 1000

Como resultado tenemos dos arreglos que si bien son objetos diferentes, tienen la misma cantidad
de elementos con los mismos valores.

 Copiar parte del contenido de un arreglo en otro arreglo:


1 class ArrayDemo4 {
2  
    public static void main(String[] args) {
3
        //declaramos y construimos un arreglo con una capacidad de diez caracteres (
4         char[] arreglo;
5         arreglo = new char[10];
6  
7         //asignamos los valores para cada posición en el arreglo...
8         arreglo[0] = 'H';
        arreglo[1] = 'o';
9
10
11
        arreglo[2] = 'l';
12         arreglo[3] = 'a';
13         arreglo[4] = ' ';
14         arreglo[5] = 'M';
15         arreglo[6] = 'u';
16         arreglo[7] = 'n';
        arreglo[8] = 'd';
17         arreglo[9] = 'o';
18  
19         //imprimimos en pantalla el valor de cada elemento en el primer arreglo...
20         for (int i = 0 ; i < arreglo.length ; i++) {
21             System.out.println("Arreglo 1 - Elemento en indice " + i + ": " + arreglo
22         }
23  
        System.out.println();
24
 
25         //declaramos y construimos un nuevo arreglo con la mitad de la capacidad del
26 anterior ("Mundo")
27         char[] arregloCopia;
28         arregloCopia = new char[5];
29  
        //copiamos el contenido del primer arreglo, comenzando desde el quinto eleme
30 segundo arreglo
31         System.arraycopy(arreglo, 5, arregloCopia, 0, 5);
32  
33         //Imprimimos en pantalla el valor de cada elemento en el segundo arreglo...
34         for (int i = 0 ; i < arregloCopia.length ; i++) {
35             System.out.println("Arreglo 2 - Elemento en indice " + i + ": " + arreglo
        }
36     }
37 }
38
39

La salida:

Arreglo 1 – Elemento en indice 0: H


Arreglo 1 – Elemento en indice 1: o
Arreglo 1 – Elemento en indice 2: l
Arreglo 1 – Elemento en indice 3: a
Arreglo 1 – Elemento en indice 4:
Arreglo 1 – Elemento en indice 5: M
Arreglo 1 – Elemento en indice 6: u
Arreglo 1 – Elemento en indice 7: n
Arreglo 1 – Elemento en indice 8: d
Arreglo 1 – Elemento en indice 9: o

Arreglo 2 – Elemento en indice 0: M


Arreglo 2 – Elemento en indice 1: u
Arreglo 2 – Elemento en indice 2: n
Arreglo 2 – Elemento en indice 3: d
Arreglo 2 – Elemento en indice 4: o
En esta ocasión hemos copiado solo una parte del primer arreglo para crear el segundo.

Arreglos multi-dimensionales

Un arreglo multi-dimensional en Java es un arreglo de arreglos, es decir hablamos de un arreglo en


el cual sus elementos también son arreglos por lo tanto podríamos tener dos índices (arreglo bi-
dimensional) o tres índices (arreglo tri-dimensional). Se hará énfasis en arreglos bi-dimensionales
ya que son los mas usados.

En un arreglo bi-dimensional tenemos la siguiente sintaxis:

nombre_arreglo[ÍNDICE][SUBÍNDICE];

Donde ÍNDICE representa las filas, y SUBÍNDICE representa las columnas.

Tanto asignar como acceder a un elemento del arreglo bi-dimensional es igual que en un arreglo
uni-dimensional, lo que cambia es la cantidad de paréntesis rectos (corchetes “[]”) que usamos
para especificar los índices. Entonces:

 Uni-dimensional: nombre_arreglo[ÍNDICE];
 Bi-dimensional: nombre_arreglo[ÍNDICE][SUBÍNDICE];
 Tri-dimensional: nombre_arreglo[ÍNDICE1][ÍNDICE2][ÍNDICE3];

Si en un arreglo uni-dimensional el índice del primer elemento es el 0, en un arreglo bi-dimensional


el índice del primer elemento (correspondiente a la esquina superior izquierda) es:

nombre_arreglo[0][0];

Por lo tanto si en un arreglo uni-dimensional el índice del ultimo elemento es nombre_arreglo.length


– 1, en un arreglo bi-dimensional el índice del ultimo elemento (correspondiente a la esquina
inferior derecha) es:
nombre_arreglo[nombre_arreglo.length - 1][nombre_arreglo[0].length - 1];

En un arreglo bi-dimensional la variable length nos puede servir para dos cosas:


 nombre_arreglo.length: nos devuelve el numero de filas.
 nombre_arreglo[0].length: nos de vuelve el numero de columnas.

Viendo un ejemplo, si necesitamos trabajar con matrices y tenemos una tabla de datos tal que:
Entonces podemos representarla con
un arreglo bi-dimensional de la siguiente forma:
1 class ArrayDemo5 {
2  
    public static void main(String[] args) {
3
        //declaramos y construimos un arreglo bidimensional de números enteros con u
4 capacidad de 2x10
5         int[][] matriz;
6         matriz = new int[2][10];
7  
8         //obtenemos el número de filas y columnas
        int filas = matriz.length;
9         int columnas = matriz[0].length;
10  
11         //imprimimos en pantalla el número de filas y columnas
12         System.out.println("Numero de filas: " + filas);
13         System.out.println("Numero de columnas: " + columnas);
14  
15         //asignamos valor a las filas
        matriz[0][0] = 0;
16         matriz[0][1] = -1;
17         matriz[0][2] = -2;
18         matriz[0][3] = -3;
19         matriz[0][4] = -4;
        matriz[0][5] = -5;
20         matriz[0][6] = -6;
21         matriz[0][7] = -7;
22         matriz[0][8] = -8;
23         matriz[0][9] = -9;
24  
25         //asignamos valor a las columnas
        matriz[1][0] = 0;
26         matriz[1][1] = 1;
27         matriz[1][2] = 2;
28         matriz[1][3] = 3;
29         matriz[1][4] = 4;
30         matriz[1][5] = 5;
        matriz[1][6] = 6;
31         matriz[1][7] = 7;
32         matriz[1][8] = 8;
33         matriz[1][9] = 9;
34  
35         //imprimimos en pantalla el valor en cada posición iterando sobre las filas
arreglo...
36         for (int x = 0 ; x < filas ; x++) {
37             //... e iterando sobre las columnas del arreglo
38
39
40             for (int y = 0 ; y < columnas ; y++) {
41                 System.out.println(matriz[x][y]); //imprimimos el valor para la posi
42 actual
43             }
44         }
    }
45 }
46
47
48

La salida:

Numero de filas: 2
Numero de columnas: 10
0
-1
-2
-3
-4
-5
-6
-7
-8
-9
0
1
2
3
4
5
6
7
8
9

En el ejemplo anterior podríamos haber echo la declaración, construcción y asignación de valores


del arreglo bi-dimensional en forma simultanea. Quedaría de la siguiente manera:

1 ...
2 int[][] matriz = {
3     { 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 },
4     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
 };
5 ...
6

Arreglos desiguales (o irregulares)


Como en Java loas arreglos multi-dimensionales son arreglos de arreglos, podríamos construir un
arreglo bi-dimensional con un cierto numero de filas y cada una de estas con un diferente numero
de columnas. A estos se le llaman arreglos desiguales y pueden ser útiles para el ahorro de
memoria. Véase:

1
2 class ArrayDemo6 {
3  
4     public static void main(String[] args) {
5         //declaramos y construimos un arreglo bidimensional de números enteros con 4
determinado de columnas
6         int[][] desigual = new int[5][0];
7  
8         //asignamos desigual cada fila su propio número de columnas
9         desigual[0] = new int[1];
10         desigual[1] = new int[2];
11         desigual[2] = new int[3];
        desigual[3] = new int[4];
12         desigual[4] = new int[5];
13  
14         //imprimimos en pantalla el numero de filas y columnas
15         System.out.println("Numero de filas: " + desigual.length);
16         System.out.println("Numero de columnas en la fila 1: " + desigual[0].length)
        System.out.println("Numero de columnas en la fila 2: " + desigual[1].length)
17         System.out.println("Numero de columnas en la fila 3: " + desigual[2].length)
18         System.out.println("Numero de columnas en la fila 4: " + desigual[3].length)
19         System.out.println("Numero de columnas en la fila 5: " + desigual[4].length)
20     }
21 }
22

La salida:

Numero de filas: 5
Numero de columnas en la fila 1: 1
Numero de columnas en la fila 2: 2
Numero de columnas en la fila 3: 3
Numero de columnas en la fila 4: 4
Numero de columnas en la fila 5: 5

El arreglo desigual anterior lo podemos visualizar de la siguiente manera:


Control de excepciones

Trabajando con arreglos nos encontraremos más de una ves con la


excepción ArrayIndexOutOfBoundsException. Esta ocurre cuando tratamos de acceder o
asignar en un índice de posición no valida del arreglo, lo que significaría que estaríamos usando un
valor negativo, mayor o igual que el tamaño del arreglo.

Recrearemos dos situaciones muy sencillas donde la JVM nos arrojaría esta excepción:

 Caso 1:
1 class ArrayDemo7 {
2  
    public static void main(String[] args) {
3         //declaramos y construimos un arreglo con una capacidad de diez números
4 enteros
5         int[] arreglo;
6         arreglo = new int[10];
7  
8         //asignamos los valores para cada posición en el arreglo...
        arreglo[0] = 100;
9         arreglo[1] = 200;
10         arreglo[2] = 300;
11         arreglo[3] = 400;
12         arreglo[4] = 500;
13         arreglo[5] = 600;
        arreglo[6] = 700;
14         arreglo[7] = 800;
15         arreglo[8] = 900;
16         arreglo[9] = 1000;
17  
18         //asignamos un valor en el décimo elemento
        arreglo[10] = 1100;
19
20  
        //imprimimos en pantalla el valor de cada elemento en el primer
21 arreglo...
22
23         for (int i = 0 ; i < arreglo.length ; i++) {
24             System.out.println("Arreglo 1 - Elemento en indice " + i + ": " +
25 arreglo[i]);
26         }
    }
27 }
28

La salida:

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 10


at arreglos.ArrayDemo.main(ArrayDemo.java:22)
Java Result: 1

La excepción es causada porque asignamos un valor en el índice 10, el cual en realidad esta fuera
del limite del arreglo. Al ser 10 la capacidad total el ultimo índice que corresponde al décimo
elemento es el 9.

 Caso 2:
1
2 class ArrayDemo8 {
3  
4     public static void main(String[] args) {
5         //declaramos y construimos un arreglo con una capacidad de diez números ente
6         int[] arreglo;
        arreglo = new int[10];
7
8  
        //asignamos los valores para cada posición en el arreglo...
9         arreglo[0] = 100;
10         arreglo[1] = 200;
11         arreglo[2] = 300;
12         arreglo[3] = 400;
        arreglo[4] = 500;
13         arreglo[5] = 600;
14         arreglo[6] = 700;
15         arreglo[7] = 800;
16         arreglo[8] = 900;
17         arreglo[9] = 1000;
18  
        //imprimimos en pantalla el valor de cada elemento en el primer arreglo (not
19 "<=") ...
20         for (int i = 0 ; i <= arreglo.length ; i++) {
21             System.out.println("Arreglo 1 - Elemento en indice " + i + ": " + arreglo
22         }
    }
23 }
24
25

La salida:
Arreglo 1 – Elemento en indice 0: 100
Arreglo 1 – Elemento en indice 1: 200
Arreglo 1 – Elemento en indice 2: 300
Arreglo 1 – Elemento en indice 3: 400
Arreglo 1 – Elemento en indice 4: 500
Arreglo 1 – Elemento en indice 5: 600
Arreglo 1 – Elemento en indice 6: 700
Arreglo 1 – Elemento en indice 7: 800
Arreglo 1 – Elemento en indice 8: 900
Arreglo 1 – Elemento en indice 9: 1000
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 10
at arreglos.ArrayDemo.main(ArrayDemo.java:25)
Java Result: 1
Un error típico de novatos, se recorren los elementos del arreglo con un bucle teniendo en cuenta
el tamaño del mismo con la variable length, si el arreglo tiene una capacidad de 10 elementos
esta variable devuelve 10, pero en la practica el tamaño total del arreglo equivale a (length - 1).
La solución podría ser declarar el bucle como:
1 ...
2 for (int i = 0 ; i <= (arreglo.length -1) ; i++)
3 ...

Ó más simple y más eficiente:

1 ...
2 for (int i = 0 ; i < arreglo.length ; i++)
3 ...

La ArrayIndexOutOfBoundsException es una excepción no chequeada, por lo que no


estamos obligados a tratarla.

Ordenamiento de los elementos

Podemos ordenar un arreglo de datos primitivos u objetos, para eso podemos crear nuestros
propios métodos implementando algún algoritmo de ordenación, o también tenemos en la API
estándar de Java clases como java.util.Arrays que nos facilitan la tarea. Normalmente para
la mayoría de los casos no crearíamos nuestros propios métodos, usaríamos lo que la API nos
proporciona porque seria típicamente mas eficiente y adecuado que lo que podríamos programar
nosotros mismos. Igualmente veremos un poco de estos dos caminos que podemos tomar.

Algoritmos de ordenamiento

Existen diversos algoritmos de ordenamiento, esto sirven para ordenar una secuencia dada según
una relación de orden. Se pueden clasificar por su estabilidad, complejidad computacional, el
tiempo que tarde la operación, el lugar donde se realice. Este tema es muy amplio y merece su
propio tutorial, aun así veremos dos ejemplos de algoritmos:

Ordenar por Selección


Este algoritmo consiste en buscar el elemento más pequeño en el arreglo y ponerlo en primera
posición, luego entre los restantes buscar de nuevo el mas pequeño y ponerlo en segunda
posición, y así sucesivamente hasta llegar al final. Requiere O(n2) operaciones para ordenar una
cantidad n de elementos. Una de las desventajas en comparación a otros algoritmos es que su
rendimiento no mejora en caso de que los elementos ya estén totalmente o parcialmente
ordenados.

En pseudocódigo:

algoritmo ordenSeleccion( A : arreglo de elementos )


para i=1 hasta longitud(A) - 1
minimo = i;
para j= i + 1 hasta n
si lista[j] < A[minimo] entonces
minimo = j
fin si
fin para
permutar(A[i], A[minimo])
fin para
fin algoritmo

A continuación un ejemplo de como ordenar un arreglo de números enteros:

1 class ArrayDemo9 {
2  
    //un arreglo de 10 números enteros desordenados
3     private static int numeros[] = { 7, 0, 9, 8, 1, 4, 6, 2, 3, 5 };
4
 
5     public static void main(String[] args) {
6         //imprimimos por pantalla el arreglo de números enteros
7         System.out.println("Arreglo sin orden:");
8         for (int num : numeros) {
            System.out.println(num);
9         }
10  
11         System.out.println();
12         //ordenamos en forma ascendente el arreglo de números enteros y lo imprimimo
13 pantalla
14         System.out.println("Orden ascendente:");
        ordSelAsc(numeros);
15         for (int num : numeros) {
16             System.out.println(num);
17         }
18  
19         System.out.println();
20  
21         //ordenamos en forma descendente el arreglo de números enteros y lo imprimim
por pantalla
22         System.out.println("Orden descendente:");
23         ordSelDesc(numeros);
24         for (int num : numeros) {
25             System.out.println(num);
26         }
    }
27
28  
    /**
29      * Este método ordena en forma ascendente el arreglo pasado como argumento usand
30      * algoritmo de selección.
31      */
32     static void ordSelAsc(int[] arreglo) {
        //iteramos sobre los elementos del arreglo
33         for (int i = 0 ; i < arreglo.length - 1 ; i++) {
34             int min = i;
35  
36             //buscamos el menor número
37             for (int j = i + 1 ; j < arreglo.length ; j++) {
                if (arreglo[j] < arreglo[min]) {
38                     min = j; //encontramos el menor número
39                 }
40             }
41  
42             if (i != min) {
43                 //permutamos los valores
                int aux = arreglo[i];
44                 arreglo[i] = arreglo[min];
45                 arreglo[min] = aux;
46             }
47         }
48     }
49  
    /**
50      * Este método ordena en forma descendente el arreglo pasado como argumento usan
51      * algoritmo de selección.
52      */
53     static void ordSelDesc(int[] arreglo) {
        //iteramos sobre los elementos del arreglo
54         for (int i = 0 ; i < arreglo.length - 1 ; i++) {
55             int max = i;
56  
57             //buscamos el mayor número
58             for (int j = i + 1 ; j < arreglo.length ; j++) {
59                     if (arreglo[j] > arreglo[max]) {
                        max = j; //encontramos el mayor número
60                     }
61             }
62  
63             if (i != max) {
64                 //permutamos los valores
                int aux = arreglo[i];
65
                arreglo[i] = arreglo[max];
66
67
68
69
70
71
72                 arreglo[max] = aux;
            }
73         }
74     }
75 }
76
77
78
79
80

La salida:

Arreglo sin orden:


7
0
9
8
1
4
6
2
3

Orden ascendente:
0
1
2
3
4
5
6
7
8
9

Orden descendente:
9
8
7
6
5
4
3
2
1
0
Ordenar por Inserción directa
Este algoritmo consiste en mantener una sub-lista ordenada con los elementos del arreglo e ir
insertando el resto en el lugar adecuado con respecto a los elementos ya ordenados.
Requiere O(n²) operaciones para ordenar una n cantidad elementos. Aunque es relativamente fácil
de implementar es ineficiente en comparación a otros algoritmos como QuikSort, aun así se
considera bueno cuando no se trata de ordenar muchos elementos.

En pseudocódigo:

algoritmo ordenInsercion( A : arreglo de elementos )


para i=1 hasta longitud(A) hacer
index = A[i]
j= i - 1
mientras j >= 0 y A[j] > index hacer
A[j + 1] = A[j]
j = j - 1
fin mientras
A[j + 1] = index
fin para
fin algoritmo

A continuación un ejemplo de como ordenar un arreglo de objetos:

1 class ArrayDemo10 {
2  
    //un arreglo de 10 objetos (Persona) desordenados
3     private static Persona[] personas = {
4         new Persona("Jose", 22),
5         new Persona("Eduardo", 31),
6         new Persona("Mike", 60),
7         new Persona("Alonso", 38),
        new Persona("Lenny", 40),
8         new Persona("Travis", 24),
9         new Persona("Zelmar", 76),
10         new Persona("Lucy", 47),
11         new Persona("Arnold", 35),
12         new Persona("Isabella", 19)
    };
13
 
14     public static void main(String[] args) {
15         //imprimimos por pantalla el arreglo de personas
16         System.out.println("Arreglo sin orden:");
17         for (Persona p : personas) {
            System.out.println(p);
18         }
19
 
20         System.out.println();
21  
22         //ordenamos el arreglo de personas alfabeticamente y lo imprimimos por pant
23         System.out.println("En orden alfabetico:");
24         ordInscNameAlfa(personas);
        for (Persona p : personas) {
25             System.out.println(p);
26         }
27  
28         System.out.println();
29  
30         //ordenamos el arreglo de personas alfabeticamente a la inversa y lo imprim
pantalla
31         System.out.println("En orden alfabetico inverso:");
32         ordInscNameInv(personas);
33         for (Persona p : personas) {
34             System.out.println(p);
35         }
36  
        System.out.println();
37
38  
        //ordenamos el arreglo de personas según la edad en forma ascendente y lo i
39 por pantalla
40         System.out.println("Segun la edad en orden ascendente:");
41         ordInscAgeAsc(personas);
42         for (Persona p : personas) {
            System.out.println(p);
43         }
44  
45         System.out.println();
46  
47         //ordenamos el arreglo de personas según la edad en forma descendente y lo
48 por pantalla
        System.out.println("Segun la edad en orden descendente :");
49         ordInscAgeDesc(personas);
50         for (Persona p : personas) {
51             System.out.println(p);
52         }
53     }
54  
    /**
55      * Este método ordena el arreglo lexicograficamente (alfabeticamente A-Z) .
56      */
57     static void ordInscNameAlfa(Persona[] arreglo) {
58         int in;
59  
60         for (int i = 1 ; i < arreglo.length ; i++) {
            Persona aux = arreglo[i];
61             in = i;    //inicia el desplazamiento en i
62  
63             while (in > 0 && arreglo[in - 1].getNombre().compareTo(aux.getNombre())
64                 arreglo[in] = arreglo[in - 1];    //desplaza el elemento hacia la d
65                 --in;
            }
66
67  
            arreglo[in] = aux;    //inserta elemento
68         }
69     }
70  
71     /**
72      * Este método ordena el arreglo lexicograficamente pero a la inversa (alfabeti
A).
73      */
74     static void ordInscNameInv(Persona[] arreglo) {
75         int in;
76  
77         for (int i = 1 ; i < arreglo.length ; i++) {
            Persona aux = arreglo[i];
78             in = i;    //inicia el desplazamiento en i
79
 
80             while (in > 0 && arreglo[in - 1].getNombre().compareTo(aux.getNombre())
81                 arreglo[in] = arreglo[in - 1];    //desplaza el elemento hacia la d
82                 --in;
83             }
84  
            arreglo[in] = aux;    //inserta elemento
85         }
86     }
87  
88     /**
89      * Este método ordena el arreglo según la edad en forma ascendente.
90      */
    static void ordInscAgeAsc(Persona[] arreglo) {
91         int in;
92  
93         for (int i = 1 ; i < arreglo.length ; i++) {
94             Persona aux = arreglo[i];
95             in = i;    //inicia el desplazamiento en i
96  
            while (in > 0 && arreglo[in - 1].getEdad() > aux.getEdad()) {
97                 arreglo[in] = arreglo[in - 1];    //desplaza el elemento hacia la d
98                 --in;
99             }
100  
101             arreglo[in] = aux;    //inserta elemento
102         }
    }
103
 
104     /**
105      * Este método ordena el arreglo según la edad en forma descendente.
106      */
107     static void ordInscAgeDesc(Persona[] arreglo) {
108         int in;
        for (int i = 1 ; i < arreglo.length ; i++) {
109             Persona aux = arreglo[i];
110             in = i;    //inicia el desplazamiento en i
111  
112             while (in > 0 && arreglo[in - 1].getEdad() < aux.getEdad()) {
113                 arreglo[in] = arreglo[in - 1];    //desplaza el elemento hacia la d
                --in;
114             }
115  
116             arreglo[in] = aux;    //inserta elemento
117         }
118     }
119 }
120  
/**
121  * Esta clase representa una persona con su nombre y edad.
122
123
124
125
126
127
128
129
130
131
132
 */
133 class Persona {
134  
135     private final String nombre;
136     private final int edad;
137  
138     public Persona(String nombre, int edad) {
        this.nombre = nombre;
139         this.edad = edad;
140     }
141  
142     public String getNombre() {
143         return nombre;
144     }
145  
    public int getEdad() {
146         return edad;
147     }
148  
149     @Override
150     public String toString() {
        return nombre + " - " + edad;
151
    }
152 }
153
154
155
156
157
158
159
160
161
162

La salida:

Arreglo sin orden:


Jose – 22
Eduardo – 31
Mike – 60
Alonso – 38
Lenny – 40
Travis – 24
Zelmar – 76
Lucy – 47
Arnold – 35
Isabella – 19

En orden alfabetico:
Alonso – 38
Arnold – 35
Eduardo – 31
Isabella – 19
Jose – 22
Lenny – 40
Lucy – 47
Mike – 60
Travis – 24
Zelmar – 76

En orden alfabetico inverso:


Zelmar – 76
Travis – 24
Mike – 60
Lucy – 47
Lenny – 40
Jose – 22
Isabella – 19
Eduardo – 31
Arnold – 35
Alonso – 38

Segun la edad en orden ascendente:


Isabella – 19
Jose – 22
Travis – 24
Eduardo – 31
Arnold – 35
Alonso – 38
Lenny – 40
Lucy – 47
Mike – 60
Zelmar – 76

Segun la edad en orden descendente:


Zelmar – 76
Mike – 60
Lucy – 47
Lenny – 40
Alonso – 38
Arnold – 35
Eduardo – 31
Travis – 24
Jose – 22
Isabella – 19
La siguiente tabla muestra los resultados del método int compareTo(String
anotherString), implementado en la clase String, el cual hace una comparación lexicográfica
(alfabética):
string1.compareTo(string2) Valor devuelto:
string1 < string2 <0
string1 == string2 0
string1 > string2 >0

La clase java.util.Arrays

Esta clase nos proporciona el método void sort(...) sobrecargado para utilizarse con


diferentes tipos de datos, de estos métodos los mas significativos que podemos apreciar en la API
son:
Método Descripción

void sort(int[] a)
Ordena en forma ascendente los elementos de un arreglo
de números enteros según su orden natural.
void sort(int[] a, int Ordena en forma ascendente, desde una posición hacia
fromIndex, int otra, los elementos en un arreglo de números enteros según
toIndex) su orden natura.
Ordena en forma ascendente los elementos de un arreglo
void sort(Object[] a) de objetos según la implementación de la
interface Comparable que define el método compareTo().
Ordena en forma ascendente los elementos de un arreglo
void sort(Object[] a,
Comparator c) de objetos según la implementación de la
interface Comparator pasada como argumento.
Ordena en forma ascendente, desde una posición hacia
void sort(Object[] a,
int fromIndex, int
otra, los elementos de un arreglo de objetos según la
toIndex) implementación de la interface Comparable que define el
método compareTo().
Ordena en forma ascendente, desde una posición hacia
void sort(Object[] a,
int fromIndex, int
otra, los elementos de un arreglo de objetos según la
toIndex, Comparator c) implementación de la interface Comparable pasada como
argumento.
Nota: como podemos ver cuando tenemos que ordenar objetos si no especificamos nuestro
propio Comparator los objetos a ordenar deben de estar implementando Comparable definiendo
su propio método int compareTo(). Son varias las clases que implementan Comparable, por
ejemplo la clase String implementa esta interface comparando dos strings en forma lexicográfica
(alfabética).

En el siguiente caso ordenamos un arreglo de números enteros:

1 import java.util.Arrays;
2  
3
4 class ArrayDemo11 {
5  
6     //un arreglo de 10 números enteros desordenados
    private static int numeros[] = { 7, 0, 9, 8, 1, 4, 6, 2, 3, 5 };
7
8  
    public static void main(String[] args) {
9         //imprimimos por pantalla el arreglo de numeros enteros
10         System.out.println("Arreglo sin orden:");
11         for (int num : numeros) {
12             System.out.println(num);
        }
13
14  
        System.out.println();
15  
16         //ordenamos en forma natural el arreglo de números enteros y lo imprimimos p
17 pantalla
18         System.out.println("Orden natural:");
19         Arrays.sort(numeros);
        for (int num : numeros) {
20             System.out.println(num);
21         }
22     }
23 }
24

La salida:

Arreglo sin orden:


7
0
9
8
1
4
6
2
3
5

Orden natural:
0
1
2
3
4
5
6
7
8
9

Si quisiéramos ordenar una sección del arreglo y no todo, podríamos hacer:


1
2 import java.util.Arrays;
3  
4 class ArrayDemo12 {
5  
6     //un arreglo de 10 números enteros desordenados
    private static int numeros[] = { 7, 0, 9, 8, 1, 4, 6, 2, 3, 5 };
7
 
8     public static void main(String[] args) {
9         //imprimimos por pantalla el arreglo de números enteros
10         System.out.println("Arreglo sin orden:");
11         for (int num : numeros) {
12             System.out.println(num);
        }
13
 
14         System.out.println();
15  
16         //ordenamos en forma natural desde la quinta posición en el arreglo de númer
17 por pantalla
18         System.out.println("Orden natural desde la quinta posicion:");
        Arrays.sort(numeros, 5, 10);
19         for (int num : numeros) {
20             System.out.println(num);
21         }
22     }
23 }
24

La salida:

Arreglo sin orden:


7
0
9
8
1
4
6
2
3
5

Orden natural desde la quinta posicion:


7
0
9
8
1
2
3
4
5
6
El orden natural es ascendente, si quisiéramos ordenar en forma descendente con el método short
deberíamos de usar un arreglo de objetos, mas exactamente para nuestro caso
necesitamos Integer (Wrapper para int), y especificar un Comparator que impone el orden
inverso al orden natural el cual tomaremos de la clase java.util.Collections. Véase:
1
2 import java.util.Arrays;
3 import java.util.Collections;
4  
5 class ArrayDemo13 {
6  
    //un arreglo de 10 números enteros desordenados
7
    private static Integer numeros[] = { 7, 0, 9, 8, 1, 4, 6, 2, 3, 5 };
8
 
9     public static void main(String[] args) {
10         //imprimimos por pantalla el arreglo de números enteros
11         System.out.println("Arreglo sin orden:");
12         for (int num : numeros) {
            System.out.println(num);
13         }
14  
15         System.out.println();
16  
17         //ordenamos en forma descendente el arreglo de números enteros y lo imprimim
18 por pantalla
19         System.out.println("Orden descendente:");
        Arrays.sort(numeros, Collections.reverseOrder());
20         for (int num : numeros) {
21             System.out.println(num);
22         }
23     }
}
24
25

La salida:

Arreglo sin orden:


7
0
9
8
1
4
6
2
3
5

Orden descendente:
9
8
7
6
5
4
3
2
1
0

Ya que ahora estamos trabajando con objetos aplicaremos los mismos procedimientos con
cadenas de texto (strings):

1
2
3 import java.util.Arrays;
import java.util.Collections;
4
5  
class ArrayDemo14 {
6
 
7     //un arreglo de 10 strings desordenados
8     private static String cadenas[] = { "hi", "Mañana" , "¿?", "0" , "abc" , "mundo",
9 "ABC" };
10  
11     public static void main(String[] args) {
        //imprimimos por pantalla el arreglo de strings
12         System.out.println("Arreglo sin orden:");
13         for (String str : cadenas) {
14             System.out.println(str);
15         }
16  
17         System.out.println();
18  
        //ordenamos en forma natural el arreglo de strings y lo imprimimos por panta
19         System.out.println("Orden natural:");
20         Arrays.sort(cadenas);
21         for (String str : cadenas) {
22             System.out.println(str);
        }
23
24  
        System.out.println();
25  
26         //ordenamos en forma inversa el arreglo de strings y lo imprimimos por panta
27         System.out.println("Orden inverso:");
28         Arrays.sort(cadenas, Collections.reverseOrder());
29         for (String str : cadenas) {
            System.out.println(str);
30         }
31     }
32 }
33
34

La salida:
Arreglo sin orden:
hi
Mañana
¿?
0
abc
mundo
-5
2
5d
ABC

Orden natural:
-5
0
2
5d
ABC
Mañana
abc
hi
mundo
¿?

Orden inverso:
¿?
mundo
hi
abc
Mañana
ABC
5d
2
0
-5

El orden natural para tratar los strings es el valor de sus caracteres ASCII.

Definiendo el orden natural de un objeto

Para esto consideraremos el mismo arreglo de personas visto antes en la implementación del
algoritmo de inserción, la diferencia será que en la clase Persona implementaremos la
interface Comparable de la cual tenemos que implementar el método int compareTo(Object
o) que definirá el orden natural del objeto en cuestión. La implementación de esta interface es
necesaria para poder ordenar cómodamente un arreglo usando el método void sort(Object[]
a), el algoritmo de ordenamiento usado por este método es una versión modificada del Algoritmo
de Mezcla (en inglés: Merge Sort).

Comencemos con el orden por nombre:

1 import java.util.Arrays;
2  
3 class ArrayDemo15 {
4  
    //un arreglo de 10 objetos (Persona) desordenados
5     static Persona[] personas = {
6         new Persona("Jose", 22),
7         new Persona("Eduardo", 31),
8         new Persona("Mike", 60),
9         new Persona("Alonso", 38),
        new Persona("Lenny", 40),
10         new Persona("Travis", 24),
11         new Persona("Zelmar", 76),
12         new Persona("Lucy", 47),
13         new Persona("Arnold", 35),
14         new Persona("Isabella", 19)
    };
15
 
16     public static void main(String[] args) {
17         //imprimimos por pantalla el arreglo de personas
18         System.out.println("Arreglo sin orden:");
19         for (Persona p : personas) {
            System.out.println(p);
20         }
21
 
22         System.out.println();
23  
24         //ordenamos naturalmente el arreglo de personas y lo imprimimos por pantalla
25         System.out.println("En orden natural:");
26         Arrays.sort(personas);
        for (Persona p : personas) {
27             System.out.println(p);
28         }
29     }
30 }
31  
32 /**
 * Esta clase representa una persona almacenando su nombre y su edad.
33  * Implementa Comparable para establecer el orden natural en caso de
34  * ser comparado int compareTo(Object o).
35  */
36 class Persona implements Comparable {
37  
    private final String nombre;
38     private final int edad;
39  
40     public Persona(String nombre, int edad) {
41         this.nombre = nombre;
42         this.edad = edad;
43     }
44  
    public String getNombre() {
45         return nombre;
46     }
47  
48     public int getEdad() {
49         return edad;
50
51
52
53
54
55     }
56  
    @Override
57
    public String toString() {
58         return nombre + " - " + edad;
59     }
60  
61     /**
62      * En este método comparamos el dato que preferimos de nuestro objeto con el
correspondiente
63      * de otro objeto.
64      */
65     public int compareTo(Object o) {
66         //hacemos un casting del objeto pasado como argumento
67         Persona p = (Persona) o;
68  
        //comparamos el nombre de este objeto con el nombre del otro objeto
69         return this.nombre.compareTo(p.getNombre());
70     }
71 }
72
73
74
75
76

La salida:

Arreglo sin orden:


Jose – 22
Eduardo – 31
Mike – 60
Alonso – 38
Lenny – 40
Travis – 24
Zelmar – 76
Lucy – 47
Arnold – 35
Isabella – 19

En orden natural:
Isabella – 19
Jose – 22
Travis – 24
Eduardo – 31
Arnold – 35
Alonso – 38
Lenny – 40
Lucy – 47
Mike – 60
Zelmar – 76
Como vemos lo único que hacemos en el método int compareTo(Object o) es comparar los
nombres (strings) con el mismo método (compareTo()) implementado por la clase String, que
como habíamos visto antes realiza una comparación lexicográfica (alfabética) que retorna -1, 0 o 1
(recordar la taba), ese resultado de esa comparación es el que retornamos desde nuestra
implementación.
Si quisiéramos que el orden natural de estos objetos fuera por su edad, simplemente cambiaríamos
el cuerpo del método int compareTo(Object o) a lo siguiente:
1 ...
    public int compareTo(Object o) {
2         //hacemos un casting del objeto pasado como argumento
3         Persona p = (Persona) o;
4  
5         if (this.edad == p.edad) {         //si la edad de este objeto es igual a la
6 retornamos 0
7             return 0;
        } else if (this.edad > p.edad) {   //si la edad de este objeto es mayor a la
8 retornamos 1
9             return 1;
10         } else {                           //si la edad de este objeto es menor a la
11 retornamos -1
            return -1;
12         }
13     }
14 ...

La salida:

Arreglo sin orden:


Jose – 22
Eduardo – 31
Mike – 60
Alonso – 38
Lenny – 40
Travis – 24
Zelmar – 76
Lucy – 47
Arnold – 35
Isabella – 19

En orden natural:
Isabella – 19
Jose – 22
Travis – 24
Eduardo – 31
Arnold – 35
Alonso – 38
Lenny – 40
Lucy – 47
Mike – 60
Zelmar – 76
En este caso la comparación trataba sobre las edades, la siguiente tabla representa los resultados
que da nuestra implementacion de int compareTo (Object o):
persona1.compareTo(persona2) Valor devuelto:
persona1 < persona2 <0
persona1 == persona2 0
persona1 > persona2 >0
Pero no siempre la idea será definir el orden natural, una forma mas flexible de ordenar un arreglo
es usar el método void sort(Object[] a, Comparator<? super T> c) al cual le
pasamos un comparador (un Comparator) que establecerá el orden sin importar si los objetos
tienen un orden natural definido o no. El algoritmo de ordenamiento usado por este método es una
versión modificada del Algoritmo de Mezcla (en inglés: Merge Sort).

Siguiendo con los ejemplo anteriores, dejaremos que el orden natural de los objetos Persona sea
por la comparación de sus nombres y crearemos un comparador que comparara por sus edades:

1 import java.util.Arrays;
import java.util.Comparator;
2
3  
class ArrayDemo16 {
4
 
5     //un arreglo de 10 objetos (Persona) desordenados
6     static Persona[] personas = {
7         new Persona("Jose", 22),
8         new Persona("Eduardo", 31),
        new Persona("Mike", 60),
9         new Persona("Alonso", 38),
10         new Persona("Lenny", 40),
11         new Persona("Travis", 24),
12         new Persona("Zelmar", 76),
13         new Persona("Lucy", 47),
        new Persona("Arnold", 35),
14         new Persona("Isabella", 19)
15     };
16  
17     public static void main(String[] args) {
18         //imprimimos por pantalla el arreglo de personas
        System.out.println("Arreglo sin orden:");
19         for (Persona p : personas) {
20             System.out.println(p);
21         }
22  
23         System.out.println();
24  
25         //ordenamos naturalmente el arreglo de personas y lo imprimimos por pantall
        System.out.println("En orden natural:");
26         Arrays.sort(personas);
27         for (Persona p : personas) {
28             System.out.println(p);
        }
29
30  
        System.out.println();
31
 
32         //ordenamos con nuestro comparador el arreglo de personas y lo imprimimos p
33         System.out.println("En orden segun el comparador:");
34         Arrays.sort(personas, new OrderByAge());
35         for (Persona p : personas) {
            System.out.println(p);
36         }
37     }
38 }
39  
40 /**
41  * Esta clase representa una persona almacenando su nombre y su edad.
 * Implementa Comparable para establecer el orden natural en caso de
42  * ser comparado con int compareTo(Object o).
43  */
44 class Persona implements Comparable {
45  
46     private final String nombre;
    private final int edad;
47
48  
    public Persona(String nombre, int edad) {
49         this.nombre = nombre;
50         this.edad = edad;
51     }
52  
53     public String getNombre() {
        return nombre;
54     }
55  
56     public int getEdad() {
57         return edad;
58     }
59  
60     @Override
    public String toString() {
61         return nombre + " - " + edad;
62     }
63  
64     /**
65      * En este método comparamos el dato que preferimos de nuestro objeto con el co
     * de otro objeto.
66      */
67     public int compareTo(Object o) {
68         //hacemos un casting del objeto pasado como argumento
69         Persona p = (Persona) o;
70  
71         //comparamos el nombre de este objeto con el nombre del otro objeto
        return this.nombre.compareTo(p.getNombre());
72     }
73 }
74
75
76
77
78
79
80
81  
82 /**
83  * Esta clase es nuestro comparador, implementa la interface Comparator.
84  */
class OrderByAge implements Comparator {
85
 
86     /**
87      * En este método comparamos la edad de dos objetos Persona.
88      */
89     public int compare(Persona p1, Persona p2) {
90         if (p1.edad == p2.edad) {          //si la edad de la primer persona es igua
retornamos 0
91             return 0;
92         } else if (p1.edad > p2.edad) {    //si la edad de la primer persona es mayo
93 retornamos 1
94             return 1;
        } else {                           //si la edad de la primer persona es meno
95 retornamos -1
96             return -1;
97         }
98     }
99 }
100
101
102
103
104
105

La salida:

Arreglo sin orden:


Jose – 22
Eduardo – 31
Mike – 60
Alonso – 38
Lenny – 40
Travis – 24
Zelmar – 76
Lucy – 47
Arnold – 35
Isabella – 19

En orden natural:
Alonso – 38
Arnold – 35
Eduardo – 31
Isabella – 19
Jose – 22
Lenny – 40
Lucy – 47
Mike – 60
Travis – 24
Zelmar – 76

En orden segun el comparador:


Isabella – 19
Jose – 22
Travis – 24
Eduardo – 31
Arnold – 35
Alonso – 38
Lenny – 40
Lucy – 47
Mike – 60
Zelmar – 76
Notar el uso de genéricos en “class OrderByAge implements Comparator<Persona>“, así
nos aseguramos que tratamos con objetos de tipo Persona.
Notas:
* En las implementaciones del método int compareTo (Object o), para acceder a un dato
dentro del propio objeto no es realmente necesario usar this, aunque es redundante para el
compilador nos mejora la legibilidad del código.
* Los métodos void sort(...) utilizados están garantizados de ser estables, es decir que
elementos iguales no serán re-ordenados.

Búsqueda de elementos

Muchas veces necesitaremos buscar algún tipo de dato o algún elemento en especifico entre los
elementos de un arreglo. Para esto podemos crear nuestros propios métodos implementando algún
algoritmo de búsqueda, o también tenemos en la API estándar de Java clases
como java.util.Arrays que nos facilitan la tarea. Veremos un poco de estos dos caminos.

Algoritmos de búsqueda

Un algoritmo de búsqueda sirve para localizar un determinado elemento según una propiedad de
este dentro de una estructura de datos. Veamos:

Lineal (o secuencial)

Consiste en buscar entre los elementos desde el índice de posición 0 y seguir así sucesivamente
hasta encontrar el elemento solicitado o hasta que no haya mas elementos.
Este es el algoritmo mas sencillo pero también el menos eficiente, ideal para trabajar con pocos
elementos. Normalmente se usa cuando los elementos no fueron previamente ordenados o no se
pueden ordenar, y también se puede usar sobre elementos ya ordenados.

En pseudocódigo:

algoritmo busquedaLineal( A : arreglo de elementos, dato : dato a buscar )


para i = 0 hasta longitud(A)
si A[i] == dato entonces
devuelve verdadero
fin si
fin para
devuelve falso
fin algoritmo

A continuación un ejemplo de como buscar un numero en un arreglo:

1
2 class ArrayDemo17 {
3  
4     //un arreglo de 10 números enteros desordenados
5     private static int numeros[] = { 678, 0, 39, 125, 100, 478, 6, 540, 78, 28 };
6  
7     public static void main(String[] args) {
        //imprimimos en pantalla el resultado de buscar 125, 0, y 400 en el arreglo
8
        System.out.println("Busqueda de \"125\": " + busquedaLineal(numeros, 125));
9         System.out.println("Busqueda de \"0\": " + busquedaLineal(numeros, 0));
10         System.out.println("Busqueda de \"400\": " + busquedaLineal(numeros, 400));
11     }
12  
13     /**
     * Método que devuelve true si encuentra el dato pasado como argumento en el
14 arreglo pasado
15      * como argumento, devuelve false en caso contrario.
16      */
17     static boolean busquedaLineal(int[] arreglo, int dato) {
18         for (int i = 0 ; i < arreglo.length ; i++) {
            if (arreglo[i] == dato) {
19                 return true;
20             }
21         }
22  
23         return false;
    }
24 }
25
26

La salida:
Busqueda de “125”: true
Busqueda de “0”: true
Busqueda de “400”: false
Binaria (o Dicotómica)

Consiste en dividir la cantidad de elementos en dos secciones, superior e inferior, calculando un


índice central y si el dato a buscar coincide con ese elemento la búsqueda termina, en caso de que
el dato sea numéricamente menor al dato del elemento central se calcula el índice central de la
mitad inferior de los elementos y se repite todo el proceso. Si se excede el limite de la sección es
porque el dato no se encuentra entre los elementos.

Este algoritmo se utiliza cuando los elementos fueron previamente ordenados (forma ascendente),
el tiempo de búsqueda se reduce considerablemente ya que disminuyen las iteraciones necesarias.
Es ideal para búsquedas en una gran cantidad de elementos.

Si se aplica sobre elementos desordenados el resultado es impredecible. Si se aplica sobre


elementos donde el dato solicitado existe mas de una ves (tiene clones) no se garantiza cual se
encontrara.

En pseudocódigo:

algoritmo busquedaDicotomica( A : arreglo de elementos, dato : dato a buscar )


inf = 0
sup = longitud(A) -1
mientras inf <= sup
si dato > A[centro] entonces
inf = centro + 1
o si dato < A[centro] entonces
sup = centro - 1
o en ningun caso
fin mientras
fin mientras
fin algoritmo

A continuación un ejemplo de como buscar un número en un arreglo:

1 class ArrayDemo18 {
2  
    //un arreglo de 10 números enteros ordenados en forma ascendente
3
    private static int numeros[] = { 0 , 6, 28, 39, 78, 100, 125, 478, 540, 678 };
4
 
5     public static void main(String[] args) {
6         //imprimimos en pantalla el resultado de buscar 125, 0, y 400 en el arreglo
7         System.out.println("Busqueda de \"28\": " + busquedaDicotomica(numeros, 28))
8         System.out.println("Busqueda de \"478\": " + busquedaDicotomica(numeros,
478));
9         System.out.println("Busqueda de \"300\": " + busquedaDicotomica(numeros,
10
11
12 300));
13     }
14  
15     /**
16      * Método que devuelve true si encuentra el dato pasado como argumento en el
arreglo pasado
17      * como argumento, devuelve false en caso contrario.
18      */
19     static boolean busquedaDicotomica(int[] arreglo, int dato) {
20         int inf = 0;
        int sup = arreglo.length - 1;
21         int centro;
22
 
23         while (inf <= sup) {
24             centro = (inf + sup) / 2;
25  
26             if (dato > arreglo[centro]) {
27                 inf = centro + 1;
            } else if (dato < arreglo[centro]) {
28                 sup = centro - 1;
29             } else {
30                 break;
31             }
        }
32
33  
        if (inf > sup) {
34             return false;
35         }
36  
37         return true;
38     }
}
39
40

La salida:

Busqueda de “28”: true


Busqueda de “478”: true
Busqueda de “300”: false

La clase java.util.Arrays

Esta clase nos proporciona el método int binarySearch(...) sobrecargado para usarse con


diferentes tipos de datos, este implementa el último algoritmo que vimos anteriormente. De dichos
métodos sobrecargados, los mas significativos que podemos apreciar en la API son:
Método Descripción
int binarySearch(int[] a, int key) Busca un valor en un
arreglo de números
enteros según
su orden ascendente
establecido
previamente.
Busca un valor en un
determinado rango de
un arreglo
int binarySearch(int[] a, int fromIndex, int
de números enteros
toIndex, int key)
según su orden
ascendente establecido
previamente.
Busca un objeto en un
arreglo de objetos
según su
int binarySearch(Object[] a, Object key)
orden natural
ascendente establecido
previamente.
Busca un objeto en un
determinado rango de
un arreglo
int binarySearch(Object[] a, int fromIndex, int
de objetos según su
toIndex, Object key)
orden natural
ascendente establecido
previamente.
Busca un objeto en un
arreglo de objetos
según un Comparator
especificado que debe
ser el mismo que se
uso para ordenar
int binarySearch(T[] a, T key, Comparator <?
previamente el
super T> c)
arreglo. Si el
Comparator es null
significa que la
búsqueda será según
su orden natural
ascendente.
int binarySearch(T[] a, int fromIndex, int Busca un objeto en un
toIndex, T key, Comparator <? super T> c) determinado rango de
un arreglo
de objetos según un
Comparator
especificado que debe
ser el mismo que se
uso para ordenar
previamente el
arreglo. Si el
Comparator es null
significa que la
búsqueda será según
su orden natural
ascendente.

Usaremos esta API para el ejemplo creado anteriormente donde implementamos nuestra propia
búsqueda binaria:

import java.util.Arrays;
1  
2 class ArrayDemo19 {
3  
4     //un arreglo de 10 números enteros ordenados en forma ascendente
    private static int numeros[] = { 0 , 6, 28, 39, 78, 100, 125, 478, 540, 678 };
5
6  
    public static void main (String[] args) {
7         //imprimimos en pantalla el resultado de buscar 125, 0, y 400 en el
8 arreglo
9         System.out.println("Busqueda de \"28\": " + Arrays.binarySearch(numeros,
10 28));
        System.out.println("Busqueda de \"478\": " +
11 Arrays.binarySearch(numeros, 478));
12         System.out.println("Busqueda de \"300\": " +
13 Arrays.binarySearch(numeros, 300));
14     }
}

La salida:

Busqueda de “28”: 2
Busqueda de “478”: 7
Busqueda de “300”: -8
En la salida vemos que los dos primeros resultados son un valor positivo y el último es negativo, en
nuestra propia implementación la salida era que los dos primeros resultados eran true y el último
false.
Como vemos el método int binarySearch(int[] a, int key), al igual que sus otras
variantes sobrecargadas, devuelve un número entero del cual se nos garantiza que si es >= (mayor
o igual) que 0 es porque el dato buscado fue encontrado (caso true), y si es < (menor) que 0 es
porque no fue encontrado (caso false).
Trabajando con objetos tomaremos el ejemplo del arreglo de objetos Persona visto en la sección
de “Ordenar los Elementos”, aplicaremos los métodos int binarySearch(Object[] a,
Object key) e int binarySearch(T[] a, T key, Comparator c) pero habiendo
establecido previamente un orden para cada caso, el orden natural (ascendente) será por
comparación de nombres y el comparador por edades:
1 import java.util.Arrays;
import java.util.Comparator;
2
3  
class ArrayDemo20 {
4
 
5     //un arreglo de 10 objetos (Persona) desordenados
6     static Persona[] personas = {
7         new Persona("Jose", 22),
8         new Persona("Eduardo", 31),
        new Persona("Mike", 60),
9         new Persona("Alonso", 38),
10         new Persona("Lenny", 40),
11         new Persona("Travis", 24),
12         new Persona("Zelmar", 76),
13         new Persona("Lucy", 47),
        new Persona("Arnold", 35),
14         new Persona("Isabella", 19)
15     };
16  
17     //el comparador
18     static OrderByAge comparator = new OrderByAge();
19  
    public static void main(String[] args) {
20         //imprimimos por pantalla el arreglo de personas
21         System.out.println("Arreglo sin orden:");
22         for (Persona p : personas) {
23             System.out.println(p);
24         }
25  
        System.out.println();
26
 
27          //ordenamos naturalmente el arreglo de personas y lo imprimimos por pantal
28         System.out.println("En orden natural:");
29         Arrays.sort(personas);
30         for (Persona p : personas) {
31             System.out.println(p);
        }
32
 
33         System.out.println();
34  
35         System.out.println("Busqueda de Nombre=Lenny - Edad=40 : " + Arrays.binarySe
36 40)));
37         System.out.println("Busqueda de Nombre=Mike - Edad=60 : " + Arrays.binarySea
38  
        System.out.println();
39
40  
        System.out.println("Busqueda de Nombre=Lenny - Edad=0 : " + Arrays.binarySea
41         System.out.println("Busqueda de Nombre=Mike - Edad=0 : " + Arrays.binarySear
42  
        System.out.println();
43
44  
        System.out.println("Busqueda de Nombre=? - Edad=40 : " + Arrays.binarySearch
45         System.out.println("Busqueda de Nombre=? - Edad=60 " + Arrays.binarySearch(p
46  
47         System.out.println();
48  
49         //ordenamos con nuestro comparador el arreglo de personas y lo imprimimos p
50         System.out.println("En orden segun el comparador:");
        Arrays.sort(personas, new comparator);
51         for (Persona p : personas) {
52             System.out.println(p);
53         }
54  
55         System.out.println();
56  
57         System.out.println("Busqueda de Nombre=Lenny - Edad=40 : " + Arrays.binarySe
comparator));
58         System.out.println("Busqueda de Nombre=Mike - Edad=60 : " + Arrays.binarySea
59 comparator));
60  
61         System.out.println();
62  
63         System.out.println("Busqueda de Nombre=? - Edad=40 : " + Arrays.binarySearch
comparator));
64         System.out.println("Busqueda de Nombre=? - Edad=60 : " + Arrays.binarySearch
65 comparator));
66  
67         System.out.println();
68  
69         System.out.println("Busqueda de Nombre=Lenny - Edad=0 : " + Arrays.binarySea
70 comparator));
        System.out.println("Busqueda de Nombre=Mike - Edad=0 : " + Arrays.binarySear
71 comparator));
72     }
73 }
74  
75 /**
76  * Esta clase representa una persona almacenando su nombre y su edad.
 * Implementa Comparable para establecer el orden natural en caso de
77  * ser comparado con int compareTo(Object o).
78  */
79 class Persona implements Comparable {
80  
81     private final String nombre;
    private final int edad;
82
83  
    public Persona(String nombre, int edad) {
84         this.nombre = nombre;
85         this.edad = edad;
86     }
87  
88     public String getNombre() {
        return nombre;
89     }
90
 
91     public int getEdad() {
92         return edad;
93     }
94  
95     @Override
    public String toString() {
96         return nombre + " - " + edad;
97     }
98  
99     /**
100      * En este método comparamos el dato que preferimos de nuestro objeto con el co
101      * de otro objeto.
     */
102     public int compareTo(Object o) {
103         //hacemos un casting del objeto pasado como argumento
104         Persona p = (Persona) o;
105  
106         //comparamos el nombre de este objeto con el nombre del otro objeto
        return this.nombre.compareTo(p.getNombre());
107     }
108 }
109  
110 /**
111  * Esta clase es nuestro comparador, implementa la interface Comparator.
112  */
class OrderByAge implements Comparator {
113
 
114     /**
115      * En este método comparamos la edad de dos objetos Persona.
116      */
117     public int compare(Persona p1, Persona p2) {
118         if (p1.edad == p2.edad) {          //si la edad de la primer persona es igua
            return 0;
119         } else if (p1.edad > p2.edad) {    //si la edad de la primer persona es mayo
120             return 1;
121         } else {                           //si la edad de la primer persona es meno
122             return -1;
        }
123     }
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138

La salida:

Arreglo sin orden:


Jose – 22
Eduardo – 31
Mike – 60
Alonso – 38
Lenny – 40
Travis – 24
Zelmar – 76
Lucy – 47
Arnold – 35
Isabella – 19

En orden natural:
Alonso – 38
Arnold – 35
Eduardo – 31
Isabella – 19
Jose – 22
Lenny – 40
Lucy – 47
Mike – 60
Travis – 24
Zelmar – 76

Busqueda de Nombre=Lenny – Edad=40 : 5


Busqueda de Nombre=Mike – Edad=60 : 7

Busqueda de Nombre=Lenny – Edad=0 : 5


Busqueda de Nombre=Mike – Edad=0 : 7

Busqueda de Nombre=? – Edad=40 : -1


Busqueda de Nombre=? – Edad=60 -1

En orden segun el comparador:


Isabella – 19
Jose – 22
Travis – 24
Eduardo – 31
Arnold – 35
Alonso – 38
Lenny – 40
Lucy – 47
Mike – 60
Zelmar – 76

Busqueda de Nombre=Lenny – Edad=40 : 6


Busqueda de Nombre=Mike – Edad=60 : 8

Busqueda de Nombre=? – Edad=40 : 6


Busqueda de Nombre=? – Edad=60 : 8
Busqueda de Nombre=Lenny – Edad=0 : -1
Busqueda de Nombre=Mike – Edad=0 : -1

En los resultados vemos que luego de ordenar naturalmente (por nombre) los objetos Persona, las
búsquedas son efectivas solo cuando se trata de los nombres de estos sin importar si la edad
coincide. Y luego de ordenar estos mismos objetos Persona con el comparador (por su edad),
sucede lo contrario, las búsquedas son efectivas solo cuando se trata de la edad de estos sin
importar si coincide el nombre.

Igualdad de arreglos

Dos arreglos se consideran iguales cuando ambos tienen la misma cantidad de elementos y cada
elemento del primero es igual al correspondiente elemento del segundo.

Para comparar dos arreglos usaremos el método boolean equals(...) de la


clase java.util.Arrays el cual esta sobrecargado para poder comparar arreglos con distintos
tipos de datos. Véase:
1 import java.util.Arrays;
2  
3 class ArrayDemo21 {
4  
5     public static void main(String[] args) {
6         //dos arreglos uni-dimensionales con la misma cantidad y los mismos
elementos
7         int[] vector1 = { 0, 1, 2, 3, 4, 5 , 6, 7, 8, 9 };
8         int[] vector2 = { 0, 1, 2, 3, 4, 5 , 6, 7, 8, 9 };
9  
10         boolean b= Arrays.equals(vector1, vector2);
11         System.out.println(b);
12     }
}
13

La salida:

true
Cuando queremos comparar arreglos de arreglos (arreglos multi-dimensionales) necesitamos
usar boolean deepEquals(Object[] a1, Object[] a2). Véase:
1 import java.util.Arrays;
2  
class ArrayDemo22 {
3
4  
    public static void main(String[] args) {
5
6         //dos arreglos bi-dimensionales con la misma cantidad y los mismos
7 elementos
8         int[][] matriz1 = {
            { 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 },
9             { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
10         };
11         int[][] matriz2 = {
12             { 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 },
            { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
13         };
14
 
15         boolean b = Arrays.deepEquals(matriz1, matriz2);
16         System.out.println(b);
17     }
18 }
19

La salida:

true

Conversiones

Algunas conversiones que pueden ser de utilidad cuando trabajamos con arreglos son:

Convertir un arreglo de caracteres a String

Para esto recurriremos el método String valueOf(char[] data) de la clase String. Véase:


1 class ArrayDemo23 {
2  
    //un arreglo de caracteres
3     private static char caracteres[] = { 'H', 'o', 'l', 'a', ' ', 'M', 'u', 'n', 'd',
4 'o' };
5  
6     public static void main(String[] args) {
7         //obtenemos un arreglo de caracteres como String y lo imprimimos por
8 pantalla
        String string = String.valueOf(caracteres);
9         System.out.println(string);
10     }
11 }

La salida:

Hola Mundo
Convertir un arreglo en una lista

Para esto recurriremos al método List<T> asList(T... a) de la clase java.util.Arrays,


a este le podemos pasar cualquier tipo de arreglo mientras se uni-dimensional. En el ejemplo se
trabaja con un arreglo de strings:
1
2 import java.util.ArrayList;
3 import java.util.Arrays;
4 import java.util.List;
5  
class ArrayDemo24 {
6
 
7     //un arreglo de strings
8     private static String cadenas[] = { "string1", "string2", "string3", "string4",
9 "string5" };
10  
11     //un ArrayList vacio
    private static List lista = new ArrayList();
12
13  
    public static void main(String[] args) {
14         //imprimimos en pantalla el contenido del arreglo de strings
15         System.out.println("Contenido del arreglo:");
16         for (String str : cadenas) {
17             System.out.println(str);
        }
18
 
19         System.out.println();
20  
21         //obtenemos una lista con el contenido de un arreglo y la imprimimos en
22 pantalla
23         lista = Arrays.asList(cadenas);
        System.out.println("Contenido de la lista:");
24
        for (String str : lista) {
25             System.out.println(str);
26         }
27     }
28 }
29

La salida:

Contenido del arreglo:


string1
string2
string3
string4
string5

Contenido de la lista:
string1
string2
string3
string4
string5

Documentación:
* Java™ Platform, Standard Edition 6 API Specification

También podría gustarte