Arreglos Avanzados - COMPUTOcomputo.fismat.umich.mx/.../actividades/arreglos_avanzados.pdf · Tambi...

24
Arreglos Avanzados H. Tejeda Marzo 2016 ´ Indice 1. Ordenamiento de elementos de un arreglo 1 2. Arreglos multidimensionales 7 3. Clase Arrays 12 4. Clase ArrayList 15 5. Enumeraciones 19 Se presentan a continuaci´ on algunas otras operaciones que son realizadas con los arreglos. Una en particular, el ordenamiento de los elementos, es requerida por otros algoritmos. Tambi´ en se indica como declarar y crear arreglos con m´ as de una dimensi´ on. Se revisa la clase Arrays que tiene m´ etodos para algunas de las operaciones requeridas en un arreglo, como el ordenamiento. Por su parte la clase ArrayList es una clase que permite realizar algunas operaciones adicionales que no est´ an presentes cuando se maneja un arreglo directamente. Por ´ ultimo se comentan las enumeraciones que son empleadas para crear un tipo de dato propio con un conjunto fijo de valores v´alidos. 1. Ordenamiento de elementos de un arreglo El ordenamiento es el proceso de arreglar una serie de objetos con alg´ un orden l´ogico. Cuando se ponen los objetos en orden, iniciando con el objeto que tiene el menor valor, se est´ a haciendo en orden ascendente, y si se inicia con el objeto con el valor m´as grande, se hace en orden descendente. 1

Transcript of Arreglos Avanzados - COMPUTOcomputo.fismat.umich.mx/.../actividades/arreglos_avanzados.pdf · Tambi...

Arreglos Avanzados

H. Tejeda

Marzo 2016

Indice

1. Ordenamiento de elementos de un arreglo 1

2. Arreglos multidimensionales 7

3. Clase Arrays 12

4. Clase ArrayList 15

5. Enumeraciones 19

Se presentan a continuacion algunas otras operaciones que son realizadas con los arreglos.Una en particular, el ordenamiento de los elementos, es requerida por otros algoritmos.Tambien se indica como declarar y crear arreglos con mas de una dimension. Se revisa la claseArrays que tiene metodos para algunas de las operaciones requeridas en un arreglo, comoel ordenamiento. Por su parte la clase ArrayList es una clase que permite realizar algunasoperaciones adicionales que no estan presentes cuando se maneja un arreglo directamente.Por ultimo se comentan las enumeraciones que son empleadas para crear un tipo de datopropio con un conjunto fijo de valores validos.

1. Ordenamiento de elementos de un arreglo

El ordenamiento es el proceso de arreglar una serie de objetos con algun orden logico.Cuando se ponen los objetos en orden, iniciando con el objeto que tiene el menor valor, seesta haciendo en orden ascendente, y si se inicia con el objeto con el valor mas grande, sehace en orden descendente.

1

El ordenamiento posible mas simple es el de dos valores que no esten ordenados. Se debenintercambiar los dos valores para ponerlos en orden. Suponiendo que se tienen dos variables,valA y valB, con los valores 16 y 2, respectivamente. Para intercambiar los valores se requiereusar una variable temp para que no se pierdan los valores al intercambiar, ası las sentenciasquedarıan como:

temp = valA; // 16 se asigna a temp

valA = valB; // 2 se asigna a valA

valB = temp; // 16 se asigna a valB

Si se quiere ordenar dos valores cualesquiera, valA y valB, en orden ascendente, se usa lasiguiente sentencia if para decidir si se hace el intercambio. El intercambio se hace cuandovalA es mayor que valB, de otra forma no se hace nada.

if (valA > valB) {temp = valA;

valA = valB;

valB = temp;

}

Ordenar mas de dos valores puestos en variables es mas complicado, pero esta tarea esmanejable cuando se usa un arreglo.

Varios algoritmos de ordenamiento han sido desarrollados; un algoritmo es un proceso oconjunto de pasos que resuelven un problema.

1.1. Algoritmo de ordenamiento burbuja

En el algoritmo de ordenamiento burbuja se comparan parejas de elementos contiguos,intercambiandolos si no estan ordenados. Ası los elementos mas pequenos “burbujean” a lacima de la lista, eventualmente creando una lista ordenada. El ordenamiento burbuja ni esel mas rapido, ni es la tecnica mas eficiente de ordenamiento, pero es facil de entender y damayor conocimiento de la manipulacion de elementos del arreglo.

Suponiendo que se tienen valores no ordenados en un arreglo, como en la siguiente sentencia:

int [] numeros = {88, 33, 99, 22, 54};

Se compara el primer numero con el segundo, si no estan ordenados ascendentemente seintercambian. Luego se repite lo anterior para el segundo con el tercero, y ası sucesivamente,hasta terminar con el cuarto y el quinto. En general se compara si numeros[x] es mayor

2

que numeros[x + 1] para intercambiarlos. En la siguiente tabla se muestran en la primeracolumna los numeros que son comparados, la segunda columna informa si la pareja de valoresson intercambiados y la ultima muestra los valores del arreglo como van acomodando.

Valores Arreglocomparados ¿Intercambio? numeros

88 > 33 Sı 88, 33, 99, 22, 54

88 > 99 No 33, 88, 99, 22, 54

99 > 22 Sı 33, 88, 99, 22, 54

99 > 54 Sı 33, 88, 22, 99, 54

33, 88, 22, 54, 99

Cuando se alcanza el fondo de la lista, los numeros no estan en orden ascendente, pero elnumero mas grande, 99, se ha movido al fondo de la lista. Esta caracterıstica da al ordena-miento burbuja su nombre, el valor “mas pesado” se ha hundido en el fondo de la lista y losvalores “mas ligeros” han burbujeado a la cima.

Suponiendo que b y temp han sido declaradas como variables enteras, el codigo para lorealizado previamente es:

for (b = 0; b < numeros.length - 1; ++b)

if (numeros[b] > numeros[b+1]) {temp = numeros[b];

numeros[b] = numeros[b+1];

numeros[b+1] = temp;

}

Nota. En vez de comparar b con numeros.length - 1 en cada iteracion del ciclo, es mas

eficiente declarar una variable a la cual se le asigne numeros.length - 1 y usarla en la

comparacion. De esta forma, la resta es hecha una sola vez.

Para continuar el ordenamiento de la lista se debe hacer nuevamente el procedimiento decomparacion-intercambio, en la siguiente tabla se describe el procedimiento.

Valores Arreglocomparados ¿Intercambio? numeros

33 > 88 No 33, 88, 22, 54, 99

88 > 22 Sı 33, 88, 22, 54, 99

88 > 54 Sı 33, 22, 88, 54, 99

88 > 99 No 33, 22, 54, 88, 99

33, 22, 54, 88, 99

3

Se puede observar que con una pasada mas en la lista, los valores 22 y 33 se intercambiaran,y la lista quedara en orden. Para ordenar completamente la lista en el pero caso, una enla cual los numeros originales esten en orden descendente, se requiere ir en la lista cuatroveces con el procedimiento comparacion-intercambio. A lo mas, siempre se necesitara pasarpor la lista tantas veces como su tamano menos uno. Las siguientes sentencias muestran elprocedimiento completo.

for (a = 0; a < numeros.length - 1; ++a)

for (b = 0; b < numeros.length - 1; ++b)

if (numeros[b] > numeros[b+1]) {temp = numeros[b];

numeros[b] = numeros[b+1];

numeros[b+1] = temp;

}

Al usar el ordenamiento burbuja para ordenar cualquier arreglo en orden ascendente, el valormas grande “cae” en el fondo del arreglo despues de comparar cada par de valores consecu-tivos en el arreglo una vez. La segunda vez que se recorre el arreglo haciendo comparaciones,no hay necesidad de revisar el ultimo par. Se garantiza que el valor mas grande ya esta enel fondo del arreglo. Se puede hacer el proceso de ordenamiento mas eficiente usando unavariable nueva para el ciclo for interno y reduciendo el valor en uno en cada ciclo a travesdel arreglo. Las siguientes sentencias muestran como se realiza.

int comparaciones = numeros.length - 1;

for (a = 0; a < numeros.length - 1; ++a) {for (b = 0; b < comparaciones; ++b)

if (numeros[b] > numeros[b+1]) {temp = numeros[b];

numeros[a] = numeros[b];

numeros[b] = temp;

}--comparaciones;

}

1.1.1. Ordenamiento de arreglos de objetos

Se pueden ordenar arreglos de objetos de la misma forma como se ordenan arreglos de tiposprimitivos. La diferencia principal se da cuando se hace la comparacion que determina si sehace el intercambio de dos elementos del arreglo. Con un arreglo de elementos primitivos,se comparan los dos elementos del arreglo para saber si estan desordenados. Cuando loselementos del arreglo son objetos, se ordena usando un campo particular del objeto.

Suponer que se ha creado una clase simple EmpleadoCompleto, codigo 1. La clase tiene cuatrocampos de datos y los metodos set y get para los campos.

4

1 public class EmpleadoCompleto {2 private int numero ;3 private St r ing a p e l l i d o s ;4 private St r ing nombres ;5 private double s a l a r i o ;6 public int getNumero ( ) {7 return numero ;8 }9 public St r ing g e t A p e l l i d o s ( ) {

10 return a p e l l i d o s ;11 }12 public St r ing getNombres ( ) {13 return nombres ;14 }15 public double g e t S a l a r i o ( ) {16 return s a l a r i o ;17 }18 public void setNumero ( int num ) {19 numero = num;20 }21 public void s e t A p e l l i d o s ( S t r ing aps ) {22 a p e l l i d o s = aps ;23 }24 public void setNombres ( S t r ing nom ) {25 nombres = nom ;26 }27 public void s e t S a l a r i o ( double s a l ) {28 s a l a r i o = s a l ;29 }30 }

Codigo 1: Clase EmpleadoCompleto.

Se puede escribir un programa que contenga un arreglo de cinco objetos EmpleadoCompletousando la siguiente sentencia:

EmpleadoCompleto[] empleados = new EmpleadoCompleto[5];

Despues de asignar los numeros de empleado, nombres y salarios a los objetos EmpleadoCom-pleto, se quiere ordenar los empleados por el salario. Se puede pasar el arreglo a un metodoordenaBurbuja que esta preparado para recibir el arreglo de EmpleadoCompleto, enseguidase muestra el metodo.

public static void ordenaBurbuja(EmpleadoCompleto[] arreglo) {int a, b;

EmpleadoCompleto temp;

5

int comparaciones = arreglo.length - 1;

for (a = 0; a < arreglo.length - 1; ++a) {for (b = 0; b < comparaciones; ++b)

if (arreglo[b].getSalario() > arreglo[b+1].getSalario()) {temp = arreglo[b];

arreglo[b] = arreglo[b+1];

arreglo[b+1] = temp;

}--comparaciones;

}}

El metodo ordenaBurbuja es similar al metodo usado para un arreglo de tipos primitivos,pero hay tres diferencias.

La cabecera del metodo ordenaBurbuja muestra que recibe un arreglo de tipo Emplea-

doCompleto.

La variable temp creada para intercambiar es del tipo EmpleadoCompleto. Observarque a pesar de solo los salarios de los empleados completos son comparados, no seintercambian unicamente los salarios, se intercambian cada objeto EmpleadoCompleto.

La comparacion para determinar si un intercambio se hace usa llamadas al metodogetSalario() para comparar el salario de cada objeto en el arreglo con el salario delobjeto adyacente.

1.2. Algoritmo de ordenamiento por insercion

El ordenamiento burbuja es facil de entender y manipular, pero existen otros algoritmos deordenamiento. El algoritmo ordenamiento por insercion revisa cada elemento de la listauno a la vez. Si un elemento esta desordenado respecto a cualquiera de los elementos previos,se mueve cada elemento previo hacia abajo una posicion y se inserta el elemento revisado.Este ordenamiento es similar a la tecnica que serıa mas probable de usar para ordenar ungrupo de objetos manualmente. Por ejemplo, si una lista contiene los valores 2, 3, 1, y 4, yse quiere poner en orden ascendente se prueban los valores 2 y 3, pero no se mueven porqueestan en orden. Cuando se prueba el tercer valor, 1, se mueven 2 y 3 a posiciones posterioresy se inserta 1 a la primera posicion.

Las siguientes sentencias muestran la logica que realiza un ordenamiento por insercion as-cendente usando un arreglo de enteros de 5 elementos llamado numeros. Se supone que a, b,y temp han sido declarados como enteros.

int [] numeros = {90, 85, 65, 95, 75};

6

a = 1;

while (a < numeros.length) {temp = numeros[a];

b = a - 1;

while (b >= 0 && numeros[b] > temp) {numeros[b + 1] = numeros[b];

--b;

}numeros[b + 1] = temp;

++a;

}

El ciclo externo del codigo anterior modifica una variable de control de ciclo a desde 1 hastauno menos que el tamano del arreglo. En el ciclo interno se van recorriendo los elementos dela lista parcialmente ordenada, empezando por el mayor, si estos son mayores que el elementoque se revisa. Este movimiento de los elementos es para generar un espacio dentro de la listaparcialmente ordenada donde sera puesto el elemento revisado. Si el elemento revisado esmayor que el elemento mas grande de la lista parcialmente ordenada, entonces no se haceningun cambio a la lista.

En la siguiente tabla se muestra como funciona el algoritmo de ordenamiento por insercion,en la primera columna se muestra la lista parcial ordenada, en la segunda el elemento que seesta revisando, en la tercera se indica si el elemento esta ordenado y en la cuarta columna semuestra como se queda el “hueco” en la lista parcialmente ordenada para poner el elementoque se revisa.

Lista parcial Elemento a insertar Lugar de Lista parcialordenada a insercion modificada

90 85 0 , 9085, 90 65 0 , 85, 90

65, 85, 90 95 3 65, 85, 90,65, 85, 90, 95 75 1 65, , 85, 90, 95

65, 75, 85, 90, 95

2. Arreglos multidimensionales

Un arreglo declarado y creado por una sentencia como la siguiente:

int [] numeros = new int [3];

se puede considerar como una columna de valores

7

numeros[0]

numeros[1]

numeros[2]

y cuyos elementos son accedidos usando un solo subındice, es un arreglo unidimensionalo de una dimension. Se puede pensar en el tamano del arreglo como su altura.

Java tambien soporta arreglos de dos o mas dimensiones. Los arreglo bidimensionalestienen dos o mas columnas de valores como se muestra en el cuadro 1. Las dos dimensionesrepresentan la altura y el ancho del arreglo. Otra forma de ver un arreglo bidimensional escomo un arreglo de arreglos. Se deben usar dos subındices cuando se accede un elemento enun arreglo bidimensional. Los matematicos llaman a un arreglo bidimensional una matriz ouna tabla. Un arreglo bidimensional se usa en las hojas de calculo electronicas, como Excel.

numeros[0][0] numeros[0][1] numeros[0][2] numeros[0][3]

numeros[1][0] numeros[1][1] numeros[1][2] numeros[1][3]

numeros[2][0] numeros[2][1] numeros[2][2] numeros[2][3]

Cuadro 1: representacion de un arreglo bidimensional.

Para declarar un arreglo bidimensional se ponen dos juegos de corchetes despues del tipo dearreglo. Por ejemplo, para el arreglo del cuadro 1 puede ser declarado como sigue, creandoel arreglo llamado numeros que tiene tres renglones y cuatro columnas:

int [][] numeros = new int [3][4];

Si no se proporcionan valores para los elementos en el arreglo bidimensional numerico, losvalores por defecto son cero. Se puede asignar otros valores a los elementos despues. Porejemplo para poner el valor catorce al elemento del arreglo numeros que esta en la primeracolumna del primer renglon se pone como numeros[0][0] = 14;.

Alternativamente, se puede inicializar un arreglo bidimensional con valores cuando es creado.El siguiente codigo asigna valores a numeros al declarar el arreglo:

int [][] numeros = { { 0, 2, 4, 6},{ 8, 10, 12, 14},{16, 18, 20, 22} };

El arreglo numeros contiene tres renglones y cuatro columnas. Se contiene el conjunto enterode valores dentro de un juego de corchetes internos.El primer renglon del arreglo tiene loscuatro enteros 0, 2, 4, y 6. Observar que estos cuatro valores estan puestos dentro de supropio juego de llaves interno para indicar que forman el primer renglon o el renglon cero.De igual forma se indican el resto de los renglones usando sus propios juegos de llaves. Elvalor de numeros[0][0] es 0, de numeros[0][1] es 2 y el de numeros[2][3] es 22. El valor

8

dentro del primer juego de corchetes que siguen el nombre del arreglo se refiere al renglon;el valor dentro de los segundos corchetes se refiere a la columna.

Un ejemplo de como puede emplearse un arreglo bidimensional es el siguiente. Suponer quese tiene un edificio de departamentos con cuatro niveles, la planta baja sera referida comoel piso cero, y los otros tres pisos como el uno, dos, y tres. Ademas cada uno de los pisostiene estudio (sin recamara) y departamentos con una y dos recamaras. La renta mensualpara cada tipo de departamento varıa, entre mas alto es el piso, mayor es la renta, y la rentaes mayor para departamentos con mas recamaras. La siguiente tabla muestra los montos delas rentas.

Sin Una DosPiso recamara recamara recamaras

0 4000 4500 51001 5000 5600 63002 6250 6760 74003 10000 12500 16000

Para determinar la renta de algun inquilino, se necesita saber dos cosas: el piso en el cual elinquilino renta el departamento y la cantidad de recamaras en el departamento. Dentro deun programa Java, se puede declarar un arreglo de rentas usando el siguiente codigo:

int [][] rentas = { {4000, 4500, 5100},{5000, 5600, 6300},{6250, 6760, 7400},{10000,12500,16000} };

Si se declaran dos enteros llamados piso y recamaras, entonces cualquier renta de un inqui-lino puede ser referida como rentas[piso][recamaras]. El codigo 2 muestra una aplicacionque pide al usuario el numero del piso y la cantidad de recamaras.

9

1 import javax . swing . JOptionPane ;2 public class EncontrarRenta {3 public stat ic void main ( St r ing [ ] a rgs ) {4 int [ ] [ ] r en ta s = { {4000 , 4500 , 5100} ,5 {5000 , 5600 , 6300} ,6 {6250 , 6760 , 7400} ,7 {10000 ,12500 ,16000} } ;8 St r ing entrada ;9 int piso , recamaras ;

10 entrada = JOptionPane . showInputDialog (null ,11 ” In g r e s e e l numero de l p i s o ” ) ;12 p i so = I n t e g e r . pa r s e In t ( entrada ) ;13 entrada = JOptionPane . showInputDialog (null ,14 ” In g r e s e e l numero de rec amaras” ) ;15 recamaras = I n t e g e r . pa r s e In t ( entrada ) ;16 JOptionPane . showMessageDialog (null ,17 ”La renta de l departamento con ” + recamaras +18 ” rec amara ( s ) en e l p i s o ” + p i so + ” es $” +19 r en ta s [ p i s o ] [ recamaras ] ) ;20 }21 }

Codigo 2: Aplicacion EncontrarRenta.

2.1. Pasar un arreglo bidimensional a un metodo

Para pasar un arreglo bidimensional a un metodo, solo se pasa el nombre del arreglo aligual como se hace con un arreglo unidimensional. Un metodo que recibe un arreglo bidi-mensional usa dos pares de corchetes siguiendo al tipo de dato en la lista de parametros dela cabecera del metodo. Por ejemplo, las siguientes cabeceras de metodos aceptan arreglosbidimensionales de int, double, y Empleado, respectivamente:

public static void mostrarPuntuaciones(int [][] puntuaciones)

public static boolean sonTodosPreciosAltos(double [][] precios)

public static double calcularTotalNomina(Empleado[][] plantilla)

Observar que los corchetes indicando el arreglo en la cabecera del metodo estan vacıos. Nohay necesidad de poner numeros en los corchetes porque cada nombre de arreglo pasadoes una direccion de memoria inicial. La forma como se manipulan los subındices dentro delmetodo determina como los renglones y columnas son accedidas.

10

2.2. Campo length con un arreglo bidimensional

En un arreglo unidimensional tiene un campo length que guarda la cantidad de elementos enel arreglo. Con un arreglo bidimensional, el campo length guarda la cantidad de renglonesen el arreglo. A su vez cada renglon tiene un campo length que guarda la cantidad decolumnas en el renglon. Suponiendo que se declara un arreglo rentas como sigue:

int [][] rentas = { {4000, 4500, 5100},{5000, 5600, 6300},{6250, 6760, 7400},{10000,12500,16000} };

El valor de rentas.length es cuatro porque hay cuatro renglones en el arreglo. El valor derentas[0].length es tres porque hay tres columnas en el primer renglon del arreglo rentas.Este valor es igual para el resto de los renglones.

La aplicacion MostrarRentas, codigo 3, muestra una aplicacion que usa los campos lengthasociados con el arreglo rentas para mostrar todas las rentas. La variable piso varıa desde0 hasta tres en el ciclo externo, y la variable recamaras va desde 0 hasta 2 en el ciclo interno.

1 public class MostrarRentas {2 public stat ic void main ( St r ing [ ] a rgs ) {3 int [ ] [ ] r en ta s = { {4000 , 4500 , 5100} ,4 {5000 , 5600 , 6300} ,5 {6250 , 6760 , 7400} ,6 {10000 ,12500 ,16000} } ;7 int piso , recamaras ;8 for ( p i s o = 0 ; p i s o < r en ta s . l ength ; ++pi so )9 for ( recamaras = 0 ; recamaras < r en ta s [ p i s o ] . l ength ;++recamaras )

10 System . out . p r i n t l n ( ” Piso ” + p i so + ” Recamaras ” +11 recamaras + ” Renta es $” + renta s [ p i s o ] [ recamaras ] ) ;12 }13 }

Codigo 3: Aplicacion MostrarRentas.

En un arreglo bidimensional, cada renglon tambien es un arreglo. Se puede declarar enJava cada renglon para que tenga diferente longitud. Cuando un arreglo bidimensional tienerenglones de longitudes diferentes, este es un arreglo imperfecto porque al dibujar lasterminaciones de cada renglon quedan desiguales. Se crea un arreglo imperfecto definiendola cantidad de renglones para un arreglo bidimensional, pero no definiendo la cantidad decolumnas en los renglones. Por ejemplo, suponer que se quieren guardar los primeros cincorenglones del Triangulo de Pascal. Se podrıa definir el arreglo como sigue:

int [][] triangulo = new int [5][];

11

La sentencia declara un arreglo con cinco renglones, pero los renglones no han sido creadostodavıa. Enseguida, se puede declarar los renglones individuales, dependiendo de cuantosvalores tiene cada renglon en el triangulo de Pascal, se usa un ciclo for para escribir uncodigo compacto.

for (int i = 0; i < triangulo.length; ++i)

triangulo[i] = new int [i + 1];

2.3. Arreglos multidimensionales

Java tambien soporta arreglos con tres, cuatro y mas dimensiones. El termino general paraarreglos con mas de una dimension es arreglos multidimensionales. Un arreglo de mas dedos dimensiones se requiere cuando se quiere guardar las rentas de departamentos de variosedificios. Una expresion como rentas[edificio][piso][recamaras] se refiere a una rentaespecıfica para un edificio cuyo numero de edificio es guardada en la variable edificio ycuyos numeros piso y recamaras estan guardadas en las variables piso y recamaras. Javapermite crear arreglos de cualquier tamano siempre y cuando se tenga control de las variablesque se ocupan como subındices, y no se agote la memoria de la computadora.

3. Clase Arrays

En muchas ocasiones se quiere realizar tareas similares con arreglos diferentes, por ejemplo,llenarlos con valores u ordenar sus elementos. Java proporciona la clase Arrays, la cualcontiene varios metodos utiles para manipular arreglos. El cuadro 2 muestra algunos de losmetodos mas utiles de la clase Arrays. Para cada metodo de la columna izquierda de latabla, tipo es para un tipo de dato; una version sobrecargada que existe de cada metodopara cada tipo de dato apropiado. Por ejemplo, hay una version del metodo sort() paraordenar arreglos de int, double, char, byte, float, long, short y Object.

Los metodos en la clase Arrays son metodos static, por lo que se usan con el nombrede la clase sin instanciar un objeto Arrays. La clase Arrays esta localizada en el paquetejava.util, ası que se puede usar la sentencia import java.util.* para accederla. Laaplicacion DemoArrays, codigo 4, muestra como se pueden usar algunos metodos de la claseArrays. En la clase DemoArrays, el arreglo puntuaciones es creado para guardar cincoenteros. Luego, un mensaje y la referencia arreglo son pasados al metodo mostrar(). Alejecutar la aplicacion se debe mostrar el arreglo original creado llenado con ceros. Despuesse llama al metodo Arrays.fill() con el nombre del arreglo y el numero 7, para luegomostrar el arreglo por segunda vez mostrando siete. Luego dos elementos, el segundo y elultimo, son cambiados a 3 y 8 respectivamente, y el arreglo se muestra nuevamente. Despuesse llama al metodo Arrays.sort() para ordenar en forma ascendente el arreglo y se vuelvea mostrar el arreglo por cuarta ocasion.

12

Metodo Propositostatic int binarySearch(

tipo[] a, tipo llave)

Busca en el arreglo indicado el valor dado por lallave usando busqueda binaria. Se requiere que elarreglo este ordenado en forma creciente.

static boolean equals(

tipo[] a, tipo[] b)

Devuelve true si los dos arreglos especificados delmismo tipo son iguales en cantidad de elementos yelemento a elemento en la misma posicion.

static void fill(

tipo[] a, tipo val)

Asigna el valor indicado a cada elemento del arregloindicado.

static void sort(tipo[] a) Ordena el arreglo indicado en orden ascendente.static void sort(tipo[] a,

int inicial, int final)

Ordena el rango, definido por los subındices iniciala final, del arreglo indicado en orden ascendente.

Cuadro 2: metodos utiles de la clase Arrays.

1 import java . u t i l . Arrays ;2 public class DemoArrays {3 public stat ic void main ( St r ing [ ] a rgs ) {4 int [ ] puntuac iones = new int [ 5 ] ;5 mostrar ( ” Arreg lo o r i g i n a l : ” , puntuac iones ) ;6 Arrays . f i l l ( puntuaciones , 7 ) ;7 mostrar ( ” Luego de l l e n a r con 7 : ” , puntuac iones ) ;8 puntuac iones [ 1 ] = 3 ;9 puntuac iones [ 4 ] = 8 ;

10 mostrar ( ”Luego de cambiar dos v a l o r e s : ” , puntuac iones ) ;11 Arrays . s o r t ( puntuac iones ) ;12 mostrar ( ” Luego de ordenar : ” , puntuac iones ) ;13 }14 public stat ic void mostrar ( S t r ing mensaje , int [ ] a r r e g l o ) {15 int tam = a r r e g l o . l ength ;16 System . out . p r i n t ( mensaje ) ;17 for ( int va lo r : a r r e g l o )18 System . out . p r i n t ( va l o r + ” ” ) ;19 System . out . p r i n t l n ( ) ;20 }21 }

Codigo 4: Aplicacion DemoArrays.

Los metodos binarySearch() de la clase Arrays son una manera conveniente para buscaren listas ordenadas de valores de diferentes tipos de datos. La lista debera estar en ordenascendente para usar el metodo binarySearch(). La forma como trabaja la busqueda binariausada por el metodo binarySearch() es como sigue.

Se encuentra la posicion central usando el tamano del arreglo. Si un arreglo tiene unacantidad par de elementos, esta puede ser cualquiera de las dos posiciones centrales.

13

Se compara el dato que se esta buscando con el elemento en la posicion central delarreglo y se revisa si el valor del dato es menor que el valor de la posicion central.

Si el dato esta por encima de la posicion central, se encuentra la posicion central dela mitad superior del arreglo; otro caso se encuentra la posicion central de la mitadinferior. En cualquier caso, se compara el dato con la nueva posicion central y se divideel area de busqueda en la mitad nuevamente.

Finalmente, se encuentra el valor o se determina que no esta en el arreglo.

Nota. Los programadores frecuentemente se refieren a la busqueda binaria como un proce-

dimiento “divide y venceras”. Si se ha jugado en alguna ocasion el juego en cual se trata

de adivinar que numero alguien penso, se podrıa haber usado una tecnica similar.

Suponer ahora una organizacion que usa seis codigos de una letra para productos. El codigo5 contiene la aplicacion VerificarCodigo que revisa un codigo de producto dado por elusuario. El arreglo codigos guarda seis valores en orden ascendente. El usuario ingresa uncodigo que es obtenido de la primera posicion del String usando el metodo charAt(). Luego,el arreglo de caracteres validos y el caracter ingresado por el usuario son pasados al metodoArrays.binarySearch(). Si el caracter es encontrado en el arreglo, su posicion es regresada,si el caracter no es encontrado en el arreglo, un entero negativo es devuelto y la aplicacionmuestra un mensaje de error.

Nota. El entero negativo devuelto por el metodo binarySearch() cuando el valor no es

encontrado es el equivalente negativo del tamano del arreglo. En muchas aplicaciones, no

se emplea el valor devuelto cuando no hay apareamiento, solo se considera si es negativo.

14

1 import java . u t i l . Arrays ;2 import javax . swing . JOptionPane ;3 public class Ver i f i c a rCod igo {4 public stat ic void main ( St r ing [ ] a rgs ) {5 char [ ] cod igos = { ’B ’ , ’E ’ , ’K ’ , ’M’ , ’P ’ , ’T ’ } ;6 St r ing entrada , mensaje ;7 char codigoUsuar io ;8 int p o s i c i o n ;9 entrada = JOptionPane . showInputDialog (null ,

10 ” I n g r e s a r un cod igo de producto ” ) ;11 codigoUsuar io = entrada . charAt ( 0 ) ;12 p o s i c i o n = Arrays . b inarySearch ( codigos , cod igoUsuar io ) ;13 i f ( p o s i c i o n >= 0)14 mensaje = ”La p o s i c i on de ” + codigoUsuar io + ” es ” +15 p o s i c i o n ;16 else17 mensaje = codigoUsuar io + ” es un cod igo inva l i d o ” ;18 JOptionPane . showMessageDialog (null , mensaje ) ;19 }20 }

Codigo 5: La aplicacion VerificarCodigo.

Nota. Los metodos sort() y binarySearch() en la clase Arrays son utiles y permiten

lograr resultados escribiendo menos instrucciones en vez de tener que escribir los metodos

propios. Esto no significa una perdida de tiempo de lectura acerca de los metodos de ordenar

y buscar vistos previamente. Entre mas completo sea el entendimiento de como los arreglos

son manipulados, las futuras aplicaciones seran mas utiles, eficientes y creativas.

4. Clase ArrayList

La clase ArrayList puede ser usada para crear contenedores que guarden listas de objetos.Esta clase proporciona algunas ventajas sobre los arreglos, una de ellas es que es redimen-sionable dinamicamente, es decir, que su tamano puede cambiar durante la ejecucion delprograma, esto significa que:

Se puede agregar un elemento en cualquier punto de un contenedor ArrayList, y eltamano del arreglo se expande automaticamente para acomodar el nuevo elemento.

Se puede quitar un elemento en cualquier punto de un contenedor ArrayList, y eltamano del arreglo se contrae automaticamente.

Para usar la clase ArrayList se debe usar alguna de las dos sentencias de importacion:

15

import java.util.ArrayList;

import java.util.*;

Luego, para declarar un ArrayList, se puede usar el constructor por defecto, como se muestraen el siguiente ejemplo:

ArrayList nombres = new ArrayList();

El constructor por defecto crea un ArrayList con una capacidad de 10 elementos. La capaci-dad del ArrayList es la cantidad de elementos que puede guardar sin tener que incrementarsu tamano. Por definicion, la capacidad del ArrayList es mayor que o igual a su tamano.Se puede tambien indicar una capacidad, como en la siguiente sentencia que declara unArrayList que puede guarda 20 nombres:

ArrayList nombres = new ArrayList(20);

Si se sabe que se necesitaran mas de 10 elementos desde el principio, es mas eficiente crearun ArrayList con una capacidad mayor que la asignada por el constructor.

El cuadro 3 resume algunos de los metodos mas utiles del ArrayList, el tipo E indica quepuede emplearse cualquier tipo, siempre y cuando al crear la coleccion se indique el tipoparticular que la coleccion manejara, ver la seccion 4.1 Limitaciones de la clase ArrayList

Metodo Propositopublic void add(E e) Agrega el elemento indicado al final de la lista.public void add(int i, E e) Inserta el elemento e en la posicion especificada.public E remove(int i) Quita y devuelve el elemento en la posicion indica-

da.public void set(int i, E e) Reemplaza el elemento en posicion indicada con el

elemento e.public E get(int i) Devuelve el elemento de la posicion indicada.public int size() Regresa la cantidad de elementos.

Cuadro 3: Metodos utiles de la clase ArrayList.

Nota. La clase Object es la clase de Java mas generica, esta clase es la raız de todas las

clases.

Para agregar un elemento al final de un ArrayList se usa el metodo add. Suponer que sequiere agregar el nombre “Javier” al ArrayList llamado nombres, entonces usar la siguientesentencia:

16

nombres.add("Javier");

Se puede insertar un elemento en una posicion especıfica en un ArrayList usando una versionsobrecargada del metodo add() que incluye la posicion. Para insertar el nombre “Juana” enla primera posicion del ArrayList nombres, usar la siguiente sentencia:

nombres.add(0, "Juana");

Con algunos de los metodos descritos en la tabla 3, se recibe un mensaje de error si laposicion es invalida para el ArrayList. Tambien estan disponibles metodos para modificary quitar elementos de un ArrayList. Con el metodo size() se puede saber la cantidad deelementos que tiene un ArrayList, no confundir con la capacidad del ArrayList.

En la aplicacion DemoArrayList, codigo 6, se muestran algunos de los metodos mencionados.

1 import java . u t i l . ArrayList ;2 public class DemoArrayList {3 public stat ic void main ( St r ing [ ] a rgs ) {4 ArrayList nombres = new ArrayList ( ) ;5 nombres . add ( ”Aixa” ) ; // agregar a l f i n a l6 mostrar ( nombres ) ;7 nombres . add ( ” Alejandro ” ) ; // agregar a l f i na l d rawback8 mostrar ( nombres ) ;9 nombres . add ( ”Ana Karen” ) ; // agregar a l f i n a l

10 mostrar ( nombres ) ;11 nombres . add (2 , ”Benjamin” ) ; // agregar en l a 3a p o s i c i on12 mostrar ( nombres ) ;13 nombres . remove ( 1 ) ; // qu i t a r e l segundo nombre14 mostrar ( nombres ) ;15 nombres . s e t (0 , ” Car los ” ) ; // modi f i car l a primera p o s i c i on16 mostrar ( nombres ) ;17 }18 public stat ic void mostrar ( ArrayList nombres ) {19 System . out . p r i n t l n ( ”\nEl tamano de l a l i s t a es ” +20 nombres . s i z e ( ) ) ;21 for ( int i =0; i<nombres . s i z e ( ) ; ++i )22 System . out . p r i n t l n ( ” p o s i c i on ” + ( i +1) + ” Nombre : ” +23 nombres . get ( i ) ) ;24 }25 }

Codigo 6: Aplicacion DemoArrayList.

En la aplicacion DemoArrayList, codigo 6, se crea un ArrayList y luego se agrega “Aixa”.Enseguida el ArrayList es pasado al metodo mostrar() para desplegar el tamano actual deesta y todos los nombres en la lista. Ejecutar la aplicacion DemoArrayList para observar la

17

salida de la aplicacion indicando un tamano de 1 y mostrando un solo nombre. Revisandosimultaneamente el codigo 6 y la salida de la aplicacion se puede entender como el ArrayListes modificado conforme los nombres son agregados, quitados, y reemplazados.

Se puede mostrar los contenidos de un ArrayList de String sin iterar a traves de los valores.En la aplicacion DemoArrayList2, codigo 7, se muestra un ArrayList llamado estudiantes

que el usuario llena interactivamente. Se muestra el arreglo de nombres como una listaseparada con comas y encerrada entre corchetes, al concatenar un String con el ArrayListen la lınea .

1 import java . u t i l . ArrayList ;2 import javax . swing . JOptionPane ;3 public class DemoArrayList2 {4 public stat ic void main ( St r ing [ ] a rgs ) {5 ArrayList e s t u d i a n t e s = new ArrayList ( ) ;6 St r ing nombre ;7 f ina l int LIMITE = 4 ;8 for ( int i =0; i<LIMITE ; ++i ) {9 nombre = JOptionPane . showInputDialog (null ,

10 ” I n g r e s a r e l nombre de l e s tud i an t e ” ) ;11 e s t u d i a n t e s . add ( nombre ) ;12 }13 System . out . p r i n t l n ( ”Los nombres son : ” + e s t u d i a n t e s ) ;14 }15 }

Codigo 7: Aplicacion DemoArrayList2

Nota. Se pueden lograr resultados similares usando un ArrayList con cualquier tipo de

clase. Recordar que cada clase contiene un metodo toString() que convierte su objeto a

un String; este metodo es usado cuando se muestra el ArrayList. Para que la cadena

devuelta por toString() sea util es necesario invalidarlo con una implementacion propia.

Con el metodo de clase sort() de java.util.Collections se puede ordenar un ArrayList,cuando este es pasado como argumento, por ejemplo:

Collections.sort(estudiantes);

4.1. Limitaciones de la clase ArrayList

Un ArrayList puede ser usado para guardar cualquier tipo de referencia de objeto. De hecho,un ArrayList puede guardar tipos multiples. Sin embargo, esto genera dos inconvenientes:

18

No se puede usar un ArrayList para guardar tipos primitivos, como int o char,porque no son referencias. Si se quiere trabajar con tipos primitivos, se puede crear unarreglo o usar la clase Arrays.

Cuando se quiere guardar elementos ArrayList, se deben convertir al tipo de referenciaapropiada antes de guardar, o se debe declarar un tipo de referencia en la declaracionArrayList.

Por ejemplo, si se quiere declarar un String para guardar el primer nombre en el ArrayListnombres, se deberan hacer sentencias tales como las siguientes:

String primerNombre;

primerNombre = (String)nombres.get(0);

El operador de moldeo (String) convierte el objeto generico devuelto por el metodo get()

a un String. Si no se realiza esta conversion, se recibe un mensaje de error indicando queese estan usando tipos incompatibles.

Se puede eliminar la necesidad de realizar una conversion con objetos ArrayList indicandoel tipo que un ArrayList puede guardar. Por ejemplo, se puede declarar un ArrayList denombres ası:

ArrayList<String> nombres = new ArrayList<String>();

Cuando se crea una declaracion ArrayList con un tipo especificado proporciona varias ven-tajas:

No se requiere usar el operador de conversion al recuperar un elemento del ArrayList.

Java revisa que solo elementos del tipo apropiado sean usados en la lista.

La advertencia del compilador indicando que el programa usa una operacion no revisadao insegura es eliminada.

5. Enumeraciones

Se pueden crear tipos de datos propios que tengan un conjunto finito de valores validos. Untipo de dato creado por el programador con un conjunto fijo de valores es un tipo de datoenumerado.

Para crear en Java un tipo de dato enumerado se debe usar la palabra reservada enum, unidentificador para el tipo, y un juego de llaves que contenga la lista de las constantes enum,las cuales representan los valores permitidas para el tipo. El siguiente codigo crea un tipoenumerado llamado Mes que contiene doce valores:

19

enum Mes {ENE, FEB, MAR, ABR, MAY, JUN,

JUL, AGO, SEP, OCT, NOV, DIC};

Por convencion, el identificador para el tipo enumerado inicia con una letra mayuscula. Estaconvencion tiene sentido porque un tipo enumerado es una clase. Tambien, por convencion,las constantes enum, como otras constantes, se ponen todas las letras en mayusculas. Lasconstantes no son cadenas y por lo tanto no se encierran entre comillas; son como identifi-cadores Java.

Despues de crear un tipo de dato enumerado, se puede declarar variables de ese tipo. Porejemplo, se podrıa declarar lo siguiente:

Mes mesNacimiento;

Se puede asignar cualquiera de las constantes enum a la variable. Entonces se puede codificaruna sentencia como la siguiente:

mesNacimiento = Mes.MAY;

Un tipo enumeracion como Mes es una clase, y sus constantes enum trabajan como objetosinstanciados de la clase, incluyendo el tener acceso a los metodos de la clase. Estos metodosintegrados, incluyendo los que se muestran en el cuadro 4, son de instancia, por lo que debenser usados con un objeto enum.

Tambien hay varios metodos estaticos disponibles para ser usados con enumeraciones. Estosson usados con el tipo y no con constantes individuales. La tabla 5 describe dos metodosutiles de este tipo.

Se puede declarar un tipo enumerado en su propio archivo, en tal caso el nombre del archivoempata el nombre del tipo y tiene extension .java. Tambien se puede declarar un tipo enu-merado dentro de una clase pero no dentro de un metodo. En la aplicacion DemoEnum, codigo8, declara una enumeracion Mes y muestra su uso.

20

Ejemplo conMetodo Descripcion mesNacimiento = Mes.MAY;

toString() Regresa el nombre del objeto cons-tante llamado

mesNacimiento.toString() tieneel valor “MAY”. Cuando se pa-sa mesNacimiento a print() oprintln() es convertido automati-camente a su cadena equivalente.

ordinal() Devuelve un entero que representa laposicion de la constante en la listade constantes. La primera posicion escero.

mesNacimiento.ordinal() es cua-tro.

equals() Devuelve true si su argumento esigual al valor del objeto que llama.

mesNacimiento.equals(Mes.MAY)

es true.mesNacimiento.equals(Mes.DIC)

es false.compareTo() Regresa un entero negativo si el valor

ordinal del objeto que llama es menorque el argumento, cero si son iguales,y un entero positivo si el valor ordinales mayor que el del argumento

mesNacimiento.compareTo(Mes.AGO)

es negativo.mesNacimiento.compareTo(Mes.ENE)

es positivo.mesNacimiento.compareTo(Mes.MAY)

es cero.

Cuadro 4: Algunos metodos enum no estaticos

Metodo Descripcion Ejemplo con enumeracion Mes

valueOf() El metodo acepta un parametroString y regresa una enumeracionconstante.

Mes.valueOf("SEP") regresa laconstante enum SEP.

values() El metodo regresa un arreglo de lasconstantes enumeradas.

Mes.values() regresa un arreglocon doce elementos que contienelas constantes enum.

Cuadro 5: Algunos metodos estaticos enum

21

1 import java . u t i l . Scanner ;2 public class DemoEnum {3 enum Mes {ENE, FEB, MAR, ABR, MAY, JUN,4 JUL, AGO, SEP, OCT, NOV, DIC} ;5

6 public stat ic void main ( St r ing [ ] a rgs ) {7 Mes mesNacimiento ;8 St r ing entrada ;9 int p o s i c i o n ;

10 int comparacion ;11 Scanner t e c l ado = new Scanner ( System . in ) ;12 System . out . p r i n t l n ( ”Los meses son : ” ) ;13 for (Mes mes : Mes . va lue s ( ) )14 System . out . p r i n t (mes + ” ” ) ;15 System . out . p r i n t ( ”\n\ nIngre sa r l a s pr imeras t r e s l e t r a s de ” +16 ”su mes de nacimiento >> ” ) ;17 entrada = tec l ado . nextLine ( ) . toUpperCase ( ) ;18 mesNacimiento = Mes . valueOf ( entrada ) ;19 System . out . p r i n t l n ( ”Ha ingre sado ” + mesNacimiento ) ;20 p o s i c i o n = mesNacimiento . o r d i n a l ( ) ;21 System . out . p r i n t l n ( mesNacimiento+” e s t a en l a p o s i c i on ”+p o s i c i o n ) ;22 System . out . p r i n t l n ( ”Ası e l numero de mes es ” + ( p o s i c i o n + 1 ) ) ;23 comparacion = mesNacimiento . compareTo (Mes .JUN) ;24 i f ( comparacion < 0)25 System . out . p r i n t l n ( mesNacimiento +26 ” e s t a antes en e l ano que ” + Mes .JUN) ;27 else28 i f ( comparacion > 0)29 System . out . p r i n t l n ( mesNacimiento +30 ” e s t a despues en e l ano que ” + Mes .JUN) ;31 else32 System . out . p r i n t l n ( mesNacimiento + ” es ” + Mes .JUN) ;33 }34 }

Codigo 8: La aplicacion DemoEnum.

En la aplicacion, codigo 8, una enumeracion Mes es declarada en el metodo main(), unavariable Mes es declarada en la lınea 7. En la lınea 13 la sentencia usa el ciclo for avanzado,el cual declara una variable local Mes llamada mes que toma el valor de cada elemento delarreglo devuelto por Mes.values() para mostrarlo. Luego en la aplicacion se pide que seingresen las primeras tres letras de un mes, que son convertidas a mayusculas. En la lınea 18se usa el metodo valueOf() para convertir la cadena del usuario a un valor enumerado. En lalınea 20 se obtiene la posicion del mes en la lista de enumeracion. En la lınea 23 se comparael mes ingresado con la constante JUN. Despues se tiene una sentencia if que muestra si elmes ingresado esta antes o despues de JUN en la lista, o si es igual.

Comenzando con Java 7, se pueden usar operadores de comparacion con constantes enume-

22

radas en vez de usar el metodo compareTo() para devolver un numero. El siguiente ejemplomuestra lo comentado:

if (mesNacimiento < Mes.JUN)

System.out.println(mesNacimiento +

" esta antes en el a~no que " + Mes.JUN);

Se pueden usar enumeraciones para controlar una estructura switch. La aplicacion DemoEnum2,codigo 9, declara una enumeracion Propiedad para una empresa de bienes raıces. La aplica-cion asigna uno de los valores a una variable Propiedad y luego usa una estructura switch

para mostrar un mensaje. Ejecutar esta aplicacion para revisar lo senalado.

1 public class DemoEnum2 {2 enum Propiedad {FAMILIA SOLA, FAMILIA MULTIPLE,3 CONDOMINIO, TERRENO, NEGOCIO} ;4 public stat ic void main ( St r ing [ ] a rgs ) {5 Propiedad propiedadEnVenta = Propiedad .FAMILIA MULTIPLE;6 switch ( propiedadEnVenta ) {7 case FAMILIA SOLA :8 case FAMILIA MULTIPLE:9 System . out . p r i n t l n ( ” Honorar ios 5 %” ) ;

10 break ;11 case CONDOMINIO:12 System . out . p r i n t l n ( ” Honorar ios 6 %” ) ;13 break ;14 case TERRENO:15 case NEGOCIO:16 System . out . p r i n t l n (17 ”No manejamos e s t e t i po de propiedad ” ) ;18 }19 }20 }

Codigo 9: Aplicacion DemoEnum2.

Se tienen varias ventajas creando un tipo enumeracion. Para el caso de la enumeracion Mes

mejora los programas en las siguientes formas:

1. Si no se crea un tipo enumerado para los valores del mes, se podrıa crear otro tipo,como int o String. El problema es que cualquier valor podrıa ser asignado a unavariable int o String, pero a Mes solo se pueden asignar los doce valores permitidos.

2. Se podrıa tener un comportamiento sin sentido con los valores si no se crea un tipoenumerado para los valores del mes. Por ejemplo, si se usaron enteros para representarmeses, se podrıa agregar, sustraer, multiplicar o dividir dos meses, lo cual no es logico.Los programadores dicen que usando enumeraciones hacen los valores tipo seguro.

23

Tipo seguro describe un tipo de dato para el cual solo comportamientos apropiadosson permitidos.

3. Las constantes enum proporcionan una forma de autodocumentacion. Alguien leyendoel programa podrıa malinterpretar el significado de 6 como valor de mes, pero haymenos confusion cuando se usa el identificador JUN.

4. Al igual que con otras clases, se puede tambien agregar metodos y otros campos a untipo enum.

24