PRÁCTICA No3 POO – Arreglos Objetivos El alumno conocerá el manejo de arreglos y manipulación de cadenas para la solución de problemas de ingeniería Introducción Los arreglos o arrays de Java (vectores, matrices, hiper-matrices de más de dos dimensiones) se tratan como objetos de una clase predefinida. Los arreglos son objetos, pero con algunas características propias. Algunas de sus características más importantes de los arrays son las siguientes: Los arrays se crean con el operador new seguido del tipo y número de elementos. Se puede acceder al número de elementos de un array con la variable miembro implícita length (por ejemplo, arreglo1.length). Se accede a los elementos de un array con los corchetes [] y un índice que varía de 0 a length-1. Los elementos de un array se inicializan al valor por defecto del tipo correspondiente (cero para valores numéricos, el carácter nulo para char, false para boolean, null para String y referencias). Como todos los objetos, los arrays se pasan como argumentos a los métodos por referencia. Inicialización de arrays: Los arrays se pueden inicializar con valores entre llaves {...} separados por comas. También los arrays de objetos se pueden inicializar con varias llamadas a new dentro de las llaves {...}. Si se igualan dos referencias a un array no se copia el array, sino que se tiene un array con dos nombres, apuntando al mismo y único objeto. Para la creación de una referencia a un array, son posibles dos formas: double[] x; // Esta forma es preferible double x[]; Ejemplos de declaración de arreglos de una dimensión o vectores En la siguiente declaración se define un arreglos de tipo entero, los elementos están agrupados bajo el nombre del arreglo, calif. int[] calif; char[] s; Dog [] d; // arreglo de enteros agrupados bajo el nombre calif // arreglo de caracteres agrupados bajo el nombre s // donde Dog representa una clase 1 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos En los ejemplos anteriores no se crean los objetos mismos, sino que sólo se indica la declaración de la variable. Se usa el operador new para la creación del arreglo. calif = new int[25]; d = new Dog[3]; Para inicializar el arreglo con valores específicos se realiza como en los siguientes ejemplos. char[] s2= {'a','b','v','g'}; Dog[] ds = {new Dog(), null, null}; El arreglo ds define tres objetos: el primero elemento se crea de manera explícita (se crea el objeto en memoria y puede accederse a los datos del objeto); al segundo y tercer elementos sólo se asignan la referencia nula, es decir, no se ha creado el elemento y no pueden accederse a las propiedades del mismo. String[] dias = {"lunes", "martes", "miercoles", "jueves","viernes", "sabado", "domingo"}; El arreglo dias define los nombres de los días de la semana, los cuales se acceden a través del índice: dias[0] – lunes, días[1] – martes; etc. Arreglos de multidimesionales Para crear arreglos de más de una dimensión, se indica por medio de la cantidad de corchetes que se agregan a la variable que representa el arreglo. Por ejemplo, si queremos declarar un arreglo de dos dimensiones agregamos doble corchetes, esto es: int[ ][ ] datos; En este caso, datos consta de dos dimensiones (representa una matriz) una dimensión para las filas y otra para las columnas. Un arreglo de tres dimensiones se definiría: int[ ][ ][] tabla_mes; El número de dimensiones necesario depende del problema que se esté resolviendo. Nota. Java proporciona clases para organizar o agrupar datos, las colecciones. Dichas clases proporcionan flexibilidad para el tratamiento de datos: HasTable, ArrayList, LinkedList, etc. Es importante conocer las propiedades de dichas clases para identificar si son viables para solucionar un problema dado. 2 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos Arreglos de dos dimensiones Los arreglos bidimensionales de Java se crean de un modo muy similar al de C++ (con reserva dinámica de memoria). En Java una matriz es un vector de vectores fila, es decir, un vector de referencias a los vectores fila. Con este esquema, cada fila podría tener un número de elementos diferente, representando un arreglo irregular. Una matriz puede crearse directamente, int [][] mat = new int[3][4]; se reserva memoria para un arreglo de 3x4 = 12 elementos; O bien puede crearse de modo dinámico con los siguientes pasos: 1. Crear la referencia indicando con un doble corchete que es una referencia a matriz, int[][] mat; 2. Crear el vector de referencias a las filas, mat = new int[3][]; 3. Reservar memoria para los vectores correspondientes a las filas, for (int i=0; i<3; i++); mat[i] = new int[4]; En ambos casos se crean los arreglos de la misma dimensión. Supongamos que se inicializó el arreglo mat con los datos de la Figura1. Es natural asumir que el arreglo mat contiene 12 elementos de tipo entero e imaginar que están organizados en filas y columnas como en la Figura 1. Sin embargo el arreglo mat es un arreglo con tres elementos; y cada elemento es una referencia a un arreglo que contiene cuatro elementos enteros, como se muestra en la Figura 2. Los arreglos subordinados no necesariamente deben tener la misma longitud. Es posible crear arreglos de longitudes diferentes como en la Figura 3. Figura 1. Representación equivocada del arreglo bidimensional 3 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos Figura 2 Representación correcta del arreglo bidimensional Figura 3 Representación de arreglo bidimensional irregular En la Figura 3 se representa el arreglo declarado en el siguiente código. int[][] mat = { {1, 2, 3}, {91, 92, 93, 94}, {2001, 2002} }; El primer elemento referencia a un subarreglo de 3 elementos; el segundo, a un subarreglo de 4 elementos; y el tercero, a un subarreglo de 2 elementos. 4 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos EJEMPLOS Ejercicio I En la clase TestArreglo se demuestra como acceder a los elementos de un arreglo de dos dimensiones con valores definidos explícitamente (línea 3). En la línea 8, se imprime el valor de todos los elementos para el sub arreglo de la posición cero, es decir, {1,2,3,4}; se accede por medio del nombre del arreglo más la posición deseada, mat[0] accede al subarreglo cero, y para acceder a cada elemento se indica la siguiente posición de cada elemento: posición cero = 1.posición uno = 2, posición dos = 3, etc. mat[0][0] hace referencia al elemento 1 mat[1][3] hace referencia al elemento 94 En las líneas 6,7,8 se imprimen todos los elementos del subarreglo de la posición cero. Para saber cuándo detener la impresión se usa la longitud del subarreglo, ya que el elemento cero de mat es un subarreglo posee la propiedad length, la cual nos indica la longitud de dicho arreglo en este caso es cuatro ya que {1,2,3,4} indica cuatro elementos. mat[0].length Por lo cual, para recorrer todos los subarreglos de mat es necesario realizar dos ciclos. El primer ciclo para desplazarnos por los subarreglos, los tres elementos; el segundo ciclo para desplazarnos dentro del subarreglo y extraer cada elemento. 1. La condición del primer ciclo, la determina la longitud del arreglo mat (línea 13), se utiliza el índice i para controlar las iteraciones. 2. La condición del segundo ciclo, la determina la longitud de cada subarreglo en mat (línea 16), es decir, para cada subarreglo utilizar su propiedad lengh, aunque en este caso son todos de la misma longitud, se utiliza el índice k para controlar las iteraciones de cada subarreglo. Para determinar la longitud de cada subarreglo se usa mat[0].length 5 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos mat[1] .length en general mat[i].length Para hacer referencia a los elementos del sub arreglo se usan ambos índices i y k mat[i][k] Lo anterior hace referencia al elemento k del subarreglo en la posición i del arreglo mat Código Clase TestArreglo 1. public class TestArreglo{ 2. public static void main (String[] args){ 3. int[ ][ ] mat = { {1, 2, 3,4}, {91, 92, 93, 94}, {2001, 2002, 2003,2004} }; 4. // imprime todos los elementos del subarreglo en la posicion cero (0) 5. System.out.print("Sub arreglo en la posición cero: "); 6. for(int i=0;i<mat[0].length;i++) 7. { 8. System.out.print(mat[0][i] + ", "); 9. } 10. System.out.println("\n--------------------------"); 11. System.out.println("Arreglo Bidimensional"); 12. // imprime cada uno de los elementos de los subarreglos 13. for(int i=0;i<mat.length;i++) 14. { 15. System.out.print("Sub arreglo " + i + ": "); 16. for(int k=0;k<mat[i].length;k++) 17. System.out.print(mat[i][k] + ", "); 18. System.out.println("\n--------------------------"); 19. } 20. } // fin main 21. } // fin clase TestArreglo Ejercicio. Modificar las línea 6,8 Línea 6. Cambiar la condición mat[0].length por mat.length Línea 8. Cambiar la impresión mat[0][i] por mat[i] ¿Qué se imprime? 6 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos Clase String La clase String nos permite encapsular cadenas de caractere. Java usa Unicode de 16-bits para soportar una amplia representación de alfabetos. Las cadenas que contiene son inmutables, es decir, una vez creada una cadena no se puede modificar su contenido. Existen varias formas de construir una cadena, por medio de caracteres, arreglo de caractes, otras cadenas, etc. Por ejemplo, podemos crear dos cadenas con el siguiente texto, ambas representaciones son válidas. String s1 = new String(“comparable”); String s2 = “comparable”; Es importante resaltar cuando se usan literales (“inmutable” en ambos ejemplos). Cada literal de cadena internamente se representa como una instancia de la clase String. Para optimizar el uso de la memoria, Java crea un pool de tales literales, cuando se crea una nueva cadena y si ya existe dicha cadena entonces sólo se hace referencia al pool donde se encuentra la cadena, esto se puede ver en la siguiente figura donde ambas cadenas hacen referencia a la misma literal. String s1 = “comparable”; String s2 = “comparable”; Para comparar dos cadenas usamos el método equals de la clase String. Este método retorna un boolean: true o false dependiendo si la s1 es igual a s2. 1. 2. 3. 4. 5. String s1 = “comparable”; String s2 = “comparable”; if (s1.equals(s2)) { // son iguales } Ya que Java mantiene un pool de literales es posible hacer referencia a la dirección de memoria de ambas cadenas s1 y s2, así podemos realizar la comparación por medio de la referencia de las variables s1 y s2 ya que apuntan a la misma literal. 1. String s1 = “comparable”; 7 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos 2. String s2 = “comparable”; 3. if (s1==s2) { 4. // si son iguales 5. } Sin embargo, si construimos nuevas instancias con por medio del constructor de strings, se crean nuevos pools de literales en el espacio del programa, y se pierde la optimización de memoria por medio de las literales. 1. 2. 3. 4. 5. String s1 = new String(“comparable”); String s2 = new String(“comparable”); if (s1==s2) { // si son iguales } En este caso se crean literales distintas hacen referencia a dos espacios diferentes; por lo que si deseamos saber si ambos contenido son iguales debemos usar el método equals aunque es más lento ya que se compara carácter por carácter. La clase String proporciona diversas formas para construir una cadena. Por ejemplo, String s = new String(“cadena”); // por medio de un texto que representa una cadena char[] cs ={„a‟,‟b‟, „c‟}; String s = new String(cs); // por medio de un arreglo de caracteres; Por medio de un arreglo de bytes, entre otros. La clase String proporciona una variedad de métodos para manipular los caracteres. En la siguiente tabla se presentan algunos métodos. Para mayores detalles consultar la documentación de Java http://java.sun.com/javase/6/docs/api/java/lang/String.html Tabla 1 Métodos de la clase String Método Tipo de dato de retorno Descripción charAt(int index) char Retorna el caracter especificado por index compareTo(String s2) int Compara lexicográficamente la cadena contra s2. Retorna 0 - si son iguales Menor a 0 – si la cadena es menor que s2 Mayor a 0 – si la cadena es mayorque s2 Ejemplo String s=”Hola Mundo” char c= s.charAt(0); // se obtiene H String s1="casa"; String s2="cama"; int res = s1.compareTo(s2); // res sera > 0 => s > m 8 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos Método Tipo de dato de retorno Descripción Ejemplo endsWith(String suf) boolean Comprueba si la cadena termina con la cadena suf String s1="casa"; if (s1.endsWith("sa")) { // Es verdadero } length() int Retorna la longitud de la cadena String s1="casa"; int x= s1.length(); // x= 4 split(String regex) String[] Divide la cadena de acuerdo al patrón regex String tex = "casa#cama#baño"; String[] aT = tex.split("#"); toUpperCase() String toLowerCase() String trim() String toCharArray() char[] Convierte la cadena a un arreglo de caracteres Convierte la cadena a minúsculas Retorna una copia de la cadena sin los espacios que tuviese en los extremos de la cadena Convierte la cadena a un arreglo de caracteres //elementos del arreglo //{“casa”, “cama”, “baño”} String s = “prueba”.toUpperCase(); //s igual a ”PRUEBA” String s = “PRUEBA”.toLowerCase(); //s igual a ”prueba” String s = “ prueba ”.trim() //s igual a ”prueba” sin espacios char[] cs= “abc”.toCharArray(); // cs es el arreglo // {„a‟,‟b‟,‟c‟} Para concatenar cadenaas, generalmente se usa el operador + (también existe el método concat() para tal operación) String s1 = “Hola” ; String s2 = “***Mundo”; String s3= s1+s2 + “…”; s3 contendrá el valor sumado: Hola***Mundo… 9 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos Ejemplo II En la clase TestCadena se hace el uso del método split() para dividir una cadena que tiene los elementos delimitados por el símbolo #. Este programa separa los elementos en un arreglo de cadenas e imprime cada elemento por separado. Para cada elemento se puede hacer un procesamiento especial. Código Clase TestCadena 1. public class TestCadena{ 2. public static void main (String[] args){ 3. 4. 5. 6. String texto = "casa#recamara#baño#sala#comedor#sala#comedor"; String[] aT = texto.split("#"); for(int k=0;k<aT.length;k++) System.out.println("Elemento " + k + ": " + aT[k]); 7. } // fin main 8. } // fin clase TestCadena Ejercicios propuestos 1. Implementar la clase que realiza las siguientes operaciones con conjuntos: El programa de prueba realizará operaciones como las siguientes: Sean A y B dos conjuntos de enteros A={1,3,4,5} B={4,3,5,6} AUB = {1,3,4,5,6} A∩B = {3,4,5} A-B = {1} A▲B = {1,6}= (A-B U B-A) = (AUB) - (A∩B) union interseccion diferencia diferenciaSim int[ ] a={1,3,4,5} int[ ] b={1,6} Conjunto c1= new Conjunto(); c1.setDatos(a); c1.union(b) // imprimirá la unión de a y b en pantalla c1.interseccion(b) // imprimirá la intersección de a y b en pantalla 10 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos Conjunto conjunto: int [ ] setDatos(c:int[ ]): void interseccion(c:int[ ]):void union(c:int[]):void diferencia(c:int[]):void diferenciaSim(c:int[]):void Los métodos sólo imprimen en pantalla los datos de los conjuntos. *Nota: Si requiere incluir más métodos para solucionar los problemas, agréguelos al diagrama de clase. 2. Implementar un analizador morfológico para palabras del español. Considerar sólo palabras adjetivas y sustantivas, implementar reglas generales para las dos categorías gramaticales: sustantivo, adjetivo. Morfologia palabra:String setPalabra(s:String): void analizarAdjetivo():void analizarSustantivo(): void Identificar para palabras adjetivas: el género (masculino , femenino) y número (plural o singular) de las palabras de acuerdo a su sufijación (final de la palabra). Por ejemplo, blancos => blanc-o-s blancas => blanc-a-s blanca => blanc-a- Ø /o/ masculino /s/ plural /a/ femenino /s/ plural /a/ femenino /vacio/ singular Identificar para palabras sustantivas: el número (plural o singular) de las palabras de acuerdo a su sufijación (final de la palabra). mujer=> mujer- Ø mujeres=> mujer-es /vacio/ singular /es/ plural 11 Elaborado por: Sabino Miranda Jiménez PRÁCTICA No3 POO – Arreglos etc. La invocación será como la siguiente: Morfologia s = new Morfologia() s.setPalabra(“salas”); s.analizarSustantivo(); // Imprimirá en pantalla los rasgos morfológicos de la palabra // salas: femenino, plural s.setPalabra(“sala”); s.analizarSustantivo(); // Imprimirá en pantalla los rasgos morfológicos de la palabra // sala: femenino, singular s.setPalabra(“rojos”); s.analizarAdjetivo(); // Imprimirá en pantalla los rasgos morfológicos de la palabra // rojos: masculino, plural *Nota: Si requiere incluir más métodos para solucionar los problemas, agréguelos al diagrama de clase. 12 Elaborado por: Sabino Miranda Jiménez