sábado, 4 de mayo de 2019

Capítulo 7 - Arreglos y colecciones

1. Conceptos y creación de arreglos


Un arreglo o array es un medio de guardar un conjunto de objetos de la misma clase. Se accede a cada elemento individual del array mediante un número entero denominado índice. Cero (0) es el índice del primer elemento y N-1 es el índice del último elemento, siendo N, la dimensión del array.

Los array tienen el atributo length que proporciona la cantidad de elementos que se pueden asignar en el array.

  • Declaración y creación de un array

Para declarar un array, se escribe lo siguiente:
tipo_de_dato[] nombre_del_array;
Para declarar un array de enteros, se escribe lo siguiente:
int[] numeros;
Para crear un array de 4 números enteros, se escribe lo siguiente:
numeros = new int[4];
La declaración y la creación del array, se puede hacer en una misma línea.
int[] numeros = new int[4];
Inicialización y uso de los elementos del array
Para inicializar el array de 4 enteros, se escribe lo siguiente:
numeros[0]=2;
numeros[1]=-4;
numeros[2]=15;
numeros[3]=-25;
Se puede inicializar en un bucle for como resultado de alguna operación. Por ejemplo:
for(int i=0; i<4; i++){
numeros[i]=i*i+4;
}
No se necesita recordar el número de elementos del array, su atributo length proporciona la dimensión del array. Así, se escribirán de forma equivalente, las siguientes líneas:
for(int i=0; i<numeros.length; i++){
numeros[i]=i*i+4;
}
Los arrays se pueden declarar, crear e inicializar en una misma línea, del
siguiente modo:
int[] numeros = {2, -4, 15, -25};String[] nombres = {"Juan", "José", "Miguel", "Antonio"};
Para imprimir a los elementos de array nombres, se escribe lo siguiente:
for(int i=0; i<nombres.length; i++){System.out.println(nombres[i]);}
Java verifica que el índice no sea mayor o igual que la dimensión del array, lo
que facilita mucho el trabajo al programador.
Para crear un array de tres objetos de la clase Rectángulo, se deberá escribir
lo siguiente:
  • Declarar

Rectangulo[] rectangulos;
  • Crear el array

rectangulos = new Rectangulo[3];
  • Inicializar los elementos del array

rectangulos[0]=new Rectangulo(10, 20, 30, 40);rectangulos[1]=new Rectangulo(30, 40);rectangulos[2]=new Rectangulo(50, 80);
O bien, se puede escribir lo anterior en una sola sentencia.
Rectangulo[] rectangulos={new Rectangulo(10, 20, 30, 40),new Rectangulo(30, 40),new Rectangulo(50, 80)};
  • Usar el array

Para calcular y mostrar el área de los rectángulos, se escribe lo siguiente:
for(int i=0; i<rectangulos.length; i++){System.out.println(rectangulos[i].calcularArea());}
  • Arrays multidimensionales

Una matriz bidimensional puede tener varias filas y en cada fila, no tiene necesariamente, que a ver el mismo número de elementos o columnas. Por ejemplo, se puede declarar e inicializar la siguiente matriz bidimensional:
double[][] matriz={{1,2,3,4}, {5,6}, {7,8,9,10,11,12}, {13}};
    • La primera fila tiene cuatro elementos {1,2,3,4}.
    • La segunda fila tiene dos elementos {5,6}.
    • La tercera fila tiene seis elementos {7,8,9,10,11,12}.
    • La cuarta fila tiene un elemento {13}.

Para mostrar los elementos de este array bidimensional, se escribe el siguiente código:
for (int i=0; i < matriz.length; i++) {for (int j=0; j < matriz[i].length; j++) {System.out.print(matriz[i][j]+"\t");}System.out.println("");}
Como se puede apreciar, matriz.length proporciona el número de filas (cuatro), mientras que matriz[i].length proporciona el número de elementos en cada fila.

Se muestran los elementos de una fila, separados por un tabulador, usando la función print. Una vez completada una fila se pasa a la siguiente mediante println.

1.1 Clases y métodos para manejar arreglos

El convertir colecciones en arrays, puede ser una tarea sencilla, pero muchas personas no saben cómo hacerlo y terminan en una instrucción for convirtiendo dato por dato. A continuación, se muestran las formas más simples de dicha conversión.
  • De una lista para un arreglo

List<String> list = new ArrayList<String>();list.add("India");list.add("Switzerland");list.add("Italy");list.add("France");Object[] countries = list.toArray(); // forma 1String[] countries = (String[]) list.toArray(new String[0]); // forma 2
  • De un arreglo para una lista

String[] countries = {"India", "Switzerland", "Italy", "France"};List list = Arrays.asList(countries);
  • De un objeto map a un arreglo

Map<String, String> map = new HashMap<String, String>();map.put("cliente", "Julio Torres");map.put("correo", "jtorres@yahoo.es");map.put("telefono", "345-4565");Object[] key = map.keySet().toArray();Object[] value = map.values().toArray();
  • De un objeto set a un arreglo

Set<String> set = new HashSet<String>();set.add("Naranja");set.add("Mandarina");set.add("Naranja"); // no permite repetidoset.add("Pera");Object[] fruta = set.toArray();
  • De una cadena a un arreglo de caracteres

String msg = "Cibertec - DAT";char[] letra = msg.toCharArray();
  • De arreglo de caracteres a una cadena

char[] charArrays = new char[]{'1', '2', '3', 'A', 'B', 'C'};String s1 = new String(charArrays); // forma 1String s2 = String.valueOf(charArrays); // forma 1

2. Java Collection Framework

Java Collection Framework o “estructura de colecciones de Java” (en adelante JCF), se trata de un conjunto de clases e interfaces que mejoran notablemente las capacidades del lenguaje respecto a estructuras de datos. Además, constituyen un excelente ejemplo de aplicación de los conceptos propios de la programación orientada a objetos. El corazón de las interfaces de colección encapsula diferentes tipos de interfaces que se muestran en la siguiente figura:



Para este caso, se desarrollarán los siguientes:
  • List y ArrayList
  • Map y HashMap
  • Set y HashSet

2.1 List y ArrayList

La clase ArrayList apoya a los vectores dinámicos que pueden crecer según sea necesario. En Java, los arrays son de una longitud fija. Después de que los arrays se crean, no pueden crecer o disminuir, lo que significa que debe saber de antemano cuántos elementos de una matriz necesita, pero, a veces, puede que no sepa hasta el tiempo de ejecución. Para manejar esta situación, JCF define la clase ArrayList que es de longitud variable, es decir, dinámicamente puede aumentar o disminuir de tamaño.

Operaciones con List y ArrayList
  • Definición de un ArrayList

List<String> list = new ArrayList< >();
    • Agregar elementos

list.add("Andrea");
list.add("Andrea");list.add("Ana");list.add("Julio");list.add("Jorge");list.add("Mary");
Obtención de un elemento
String s = list.get(0); // devuelve el primero (Andrea)

Cantidad de elementos
int ctos = list.size();

Sublista
List list2 = list.subList(1, 3); // retorna. Ana y Julio

Eliminación de un elemento
list.remove(1); // elimina el segundo

Borrar una lista
list.clear();

Verificación si la lista está vacía
boolean flag = list.isEmpty(); // true si está vacía

Retorno del contenido como un arreglo de objetos
Object[] arreglo = list.toArray();
    • Recorrer list con for (cada elemento de list, se asigna en nombre):

          for (String nombre : list) {                   System.out.println(nombre);          }

2.2 Map y HashMap

La clase hashMap permite seleccionar objetos contenidos en él, a través de un índice numérico.
Pero, ¿qué es lo que sucede cuando se realizan selecciones utilizando otros criterios? Se piensa en un mapa. Conceptualmente, todo parece ser un vector, pero en lugar de acceder a los objetos a través de un número, en realidad se utiliza otro objeto, lo cual lleva a utilizar claves.

Operaciones con Map y HashMap
Definición de una HashMap
Map<String, String> map = new HashMap<String, String>();

Agregar elementos
map.put("Andrea", "962-345-678");
map.put("Ana", "876-234-655");
map.put("Julio", "345-4565");
map.put("Jorge", "997-234-446");
map.put("Mary", "987-345-456");

Obtener un elemento
map.get("Mary"); // devuelve 987-345-456

Cantidad de elementos
int ctos = map.size();

Verificación si existe key
boolean existe = map.containsKey("Julio"); // true

Verificación si existe value
boolean existe = map.containsValue("345-4565"); // true

Eliminación de un elemento
map.remove("Ana"); // elimina Ana y 876-234-655

Limpiar un mapa
map.clear();

Verificación si la lista está vacía
boolean flag = map.isEmpty(); // true si está vacía

Retorno de sus values como una colección de cadenas
Collection<String> c = map.values();
for(String s : c) {
System.out.println(s);

El siguiente fragmento de código muestra como recorrer un objeto Map para obtener su key y value:
Map<Integer, String> datos = new HashMap<Integer, String>();
datos.put(1, "dato1");
datos.put(2, "dato2");
datos.put(3, "dato3");
for (Map.Entry<Integer, String> entry : datos.entrySet()) {
System.out.println("clave=" + entry.getKey()
+ ", valor=" + entry.getValue());
}

2.3 Set y HashSet

La clase HashSet no permite elementos repetidos. La interfaz Set contiene solo métodos heredados de Collection y aumenta la restricción de elementos duplicados.

Esta interfaz tiene un comportamiento más específico en operaciones con equals y hashCode permitiendo a instancias de esta interfaz, ser comparadas significativamente, aún si el tipo de implementación difiere. Dos instancias de Set son iguales si ellas contienen los mismos elementos. Método HashCode, este método viene a complementar al método equals y sirve para comparar objetos de una forma más rápida en estructuras Hash puesto que únicamente nos devuelve un número entero. Cuando Java compara dos objetos en estructuras de tipo hash (HashMap, HashSet etc) primero invoca al método hashcode y luego el equals. Si los métodos hashcode de cada objeto devuelven diferente, Java no seguirá comparando y considerará a los objetos distintos.

En el caso en el que ambos objetos compartan el mismo hashcode Java invocará al método equals() y revisará a detalle si se cumple la igualdad. De esta forma las búsquedas quedan simplificadas en estructuras hash. Manejando colecciones

Muchas veces se nos olvida que la invocación a los métodos equals y hashcode forma parte intrínseca del framework de colecciones. Por ejemplo, si construimos dos objetos de tipo Persona y los añadimos a unHashSet, podemos comprobar que la persona existe utilizando el método contains dentro del conjunto.



Método equals y sobreescritura de metodos equals y hashcode El método equals es el más sencillo de entender ya que comprueba si los dos objetos son del mismo tipo y si su nombre coincide. Vamos a crear una implementación por defecto para la clase Persona que realice un override sobre los métodos equals y hashcode.

2.3 Operaciones con Set y HashSet

Definición de una HashSet
Set<String> set = new HashSet<String>();

Añadir elementos
set.add("Andrea");
set.add("Ana");
set.add("Julio");
set.add("Julio"); // NO es aceptado (lo ignora)
set.add("Mary");

Obtención de la cantidad de elementos
int ctos = set.size();

Verificación si existe Julio
boolean existe = set.contains("Julio"); // true

Eliminación de un elemento
map.remove("Julio "); // elimina Julio

Borrar un set
set.clear();

Verificación si el conjunto está vacío
boolean flag = set.isEmpty(); // true si está vacío

Retorno de su contenido como un arreglo de objetos
Object[] a = set.toArray();
for(String s : a) {
System.out.println(s);
}

Suponiendo que s1 y s2 son Sets y las operaciones sobre éstos:
- s1.containsAll(s2) retorna true, si s2 es un sub conjunto de s1, es
decir si s1 contiene todos los elementos de s2.
- s1.addAll(s2) transforma a s1 en la unión de s1 más s2.
- s1.retainAll(s2) transforma a s1 en la intersección de s1 y s2. La
diferencia entre s1 y s2.

2.4 Iterator

Iterator nos permite recorrer los objetos colección del JCF, básicamente, un iterator es un apuntador a una colección, que recorre uno a uno los elementos de una colección, usa su método next() dentro de un While para recorrer los elementos de la colección. Por ejemplo, se puede recorrer una lista con un objeto iterator de la siguiente manera:



Salida en consola.



También, se puede aplicar Iterator a un Set del siguiente modo:































No hay comentarios:

Publicar un comentario