Actividad de Aprendizaje de La Unidad 2 - Estructura de Datos - Sergio Luis Arrieta Gonzalez
Actividad de Aprendizaje de La Unidad 2 - Estructura de Datos - Sergio Luis Arrieta Gonzalez
Actividad de Aprendizaje de La Unidad 2 - Estructura de Datos - Sergio Luis Arrieta Gonzalez
1.CLASE VECTOR
Vamos a continuar el estudio de la interface List del api de Java, pero esta vez nos
centraremos en la implementación de esta interface a través de la clase Vector. También
veremos las características más importantes de esta nueva implementación y haremos un
ejemplo a modo de ejercicio.
VECTOR
La clase Vector, al igual que ArrayList o LinkedList, también implementa a List, pero de
un modo especial. Este modo especial es sincronizado, lo que permite que se pueda usar en
entornos concurrentes (es decir, en varios procesos que se ejecutan al mismo tiempo y
hacen uso posiblemente de los mismos recursos). Esta además es la principal característica
que la diferencia de otras clases estudiadas anteriormente como ArrayList.
Se recomienda que si no es necesario se use ArrayList en vez de Vector. Por tanto, solo
utilizaremos la clase Vector si tenemos previstas circunstancias especiales como procesos
concurrentes.
Vamos a ver las principales características de esta clase, que además es muy parecida a
ArrayList.
Un objeto de tipo Vector contiene elementos que pueden ser accedidos por un índice y
puede aumentar o disminuir su tamaño dinámicamente en tiempo de ejecución.
Vamos a realizar un ejemplo de uso sobre la clase Vector, donde añadiremos elementos,
eliminaremos elementos y consultaremos la capacidad del vector. Para ello también
usaremos la clase Persona que hemos venido utilizando en ocasiones anteriores durante el
curso:
import java.util.Vector;
int i = 0;
while (i<15) {
v.add(new Persona(i,"Persona"+i,i));
i++; }
v.trimToSize();
v.ensureCapacity(50);
}
}
2. Java cuenta con múltiples tipos de datos para trabajar con cadenas de caracteres. El más
conocido de ellos es String, pero también tenemos a nuestra disposición otros como
StringBuilder y StringBuffer. Para elegir el más adecuado en cada caso hemos de conocer
las diferencias entre ellos. Es un conocimiento que nos será útil para mejorar el rendimiento
de nuestras aplicaciones y que, además, podría ayudarnos a responder cuestiones en una
entrevista de trabajo en la que se soliciten conocimientos sobre Java.
¿Por qué existen varios tipos de datos para la misma categoría de información?
Lo primero que habríamos de preguntarnos es la razón por la que existen múltiples tipos de
datos en Java para operar sobre una misma categoría de información: las cadenas de
caracteres.
Como se apuntaba en el artículo Cadenas compactas en Java 9 que publicábamos hace unas
semanas, una fracción importante de toda la información con la que trabajan las
aplicaciones son cadenas de caracteres. Por ello es importante que el trabajo con las mismas
sea lo más eficiente posible. Es la razón por la que en la clase String el atributo encargado
de almacenar los caracteres, tal y como se aprecia en la siguiente imagen correspondiente a
la cabecera del módulo String.java, se declare como final. Esto implica que su contenido,
una vez asignado, ya no podrá modificarse. Por esto se dice que el tipo String de Java es
inmutable.
No hemos de olvidar que Java es un lenguaje muy usado para el desarrollo de aplicaciones
de servidor, en las que es habitual la creación de múltiples hilos (threads) de ejecución a fin
de paralelizar el trabajo y aprovechar las actuales configuraciones multi-procesador y
multi-núcleo. En este contexto, un tipo inmutable aporta indudables ventajas. Las
operaciones sobre String no precisan de mecanismos de sincronización para el acceso
simultáneo desde múltiples hilos, lo cual permite trabajar con ellas con un buen
rendimiento. La sincronización implica, en general, la serialización de las operaciones,
afectando de manera importante al rendimiento con que es posible llevarlas a cabo.
Todas las ventajas suelen tener asociada una contrapartida y, en este caso concreto, la
desventaja surge al manipular el contenido de una cadena. Dado que el tipo String es
inmutable (no podemos modificar su contenido), cualquier operación de modificación sobre
una variable de este tipo, como puede ser concatenar una cadena a otra o usar métodos
como toUpperCase(), replace() o similares, implica la creación de un nuevo objeto String
como resultado. Por ejemplo:
Java está presente en más de 15.000.000.000 de dispositivos. Una razón de peso para
dominar Java. ¿Te ayudamos? »
Obviamente, el hecho de se liberen y creen nuevos objetos String cada vez que se cambia
su contenido influye también en el rendimiento de los programas. El recolector de basura
de Java tendrá más trabajo. No obstante, la decisión de hacer inmutable el tipo String parte
de análisis realizados sobre aplicaciones en los que se observa que en una gran proporción
de los casos su contenido no es modificado, por lo que los beneficios obtenidos son, en
general, superiores a los inconvenientes.
saludo.append(" mundo");
En este caso, al agregar la segunda cadena a la primera, sencillamente se actualiza el
contenido inicial de la variable saludo, de tipo StringBuilder, en lugar de liberarse el objeto
original y crearse otro nuevo. En general, un programa que vaya a modificar con cierta
frecuencia el contenido de una o más cadenas de caracteres obtendrá mejor rendimiento de
esta forma que con el tipo String original.
Como apuntaba antes, habitualmente cada ventaja conlleva algún tipo de inconveniente. La
flexibilidad de los tipos StringBuilder y StringBuffer también tiene su contrapartida. Al
contar con un contenido mutable, StringBuilder no es un tipo de dato seguro para
aplicaciones con múltiples hilos de ejecución. Si dos hilos acceden simultáneamente para
cambiar algo en la cadena, el resultado puede ser totalmente inesperado.
¿Qué hacer si necesitamos trabajar con cadenas de caracteres mutables en un entorno multi-
hilo? Usar el tipo StringBuffer en lugar de StringBuilder. Ambos son prácticamente
idénticos en cuanto a funcionalidad se refiere, pero internamente la implementación de
todos los métodos que alteran la cadena está sincronizada en el caso de StringBuffer. Es
decir, este último tipo es seguro (thread-safe) para múltiples hilos, mientras que
StringBuilder no lo es. Esta seguridad se obtiene a costa del rendimiento, ya que la
sincronización provoca que las operaciones sobre cadenas con StringBuffer sean más lentas
que con StringBuilder o que con String.
Cuando el compilador se ocupa de optimizar por nosotros
A la vista de lo explicado hasta ahora, podríamos pensar en recurrir a los tipos de cadenas
mutables exclusivamente en aquellos casos en que vamos a llevar a cabo reiteradas
operaciones de modificación, como puede ser la concatenación de un conjunto de
resultados generados en un bucle. Por ejemplo:
Al trabajar con arrays de tipos primitivos o de objetos se nos puede plantear la necesidad de
copiar arrays. La copia de arrays está permitida pero conviene ser cauto cuando realicemos
procesos de este tipo. Recordar que un array es un objeto (aunque sea especial) y por tanto
la variable que lo nombra en realidad contiene un puntero al objeto, no el objeto en sí
mismo.
Al hacer una operación del tipo array1 = array2, el puntero de array1 apunta al mismo
objeto que array2 mientras que el objeto al que apuntaba array1 queda inaccesible. A partir
de ese momento existe identidad entre los arrays y la comparación usando == nos
devolverá true. A través de código, vamos a plantearnos distintas situaciones y a comentar
cuáles son los resultados.
System.out.println("");
System.out.println("");
System.out.println("");
System.out.println("");
} //Cierre de la clase
Supongamos que queremos comparar la igualdad entre dos arrays. Una idea (mala idea)
podría ser aplicar el método equals directamente sobre el array. Un código de prueba podría
ser este:
System.out.println();
} //Cierre de la clase
Con este ejemplo comprobamos que el método equals aplicado directamente sobre arrays
no funciona ya que en el primer caso teniendo el mismo contenido nos dice que la relación
de igualdad es falsa. ¿Por qué? Porque ya dijimos en su momento que los arrays son unos
objetos especiales que no tienen una clase que los implemente. Si no tienen clase, no tienen
métodos (al menos directamente), y el método que se aplica es el usado por defecto por
Java con resultados imprevisibles o no deseados. La solución para comparar arrays es usar
otra clase que permite realizar operaciones con arrays. Esta clase es la clase Arrays. Una
vez más la terminología Java nos puede inducir a confusión: hablamos de array como
colección de tipos primitivos u objetos, y al mismo tiempo Arrays (con mayúsculas) es el
nombre de una clase Java que sirve para manipular arrays.
Devuelve true si los dos arrays especificados tienen relación de igualdad entre sí.
Vamos a aplicar este método para comparar el contenido de dos arrays de enteros (relación
de igualdad). La aplicación al resto de tipos primitivos y objetos es análoga. La sintaxis en
general es: Arrays.equals (nombreArray1, nombreArray2).
EJERCICIO EJEMPLO RESUELTO 3. COMPARAR ARRAYS (RELACIÓN DE
IGUALDAD) USANDO LA CLASE ARRAYS
import java.util.Arrays;
//Test comparar arrays relación de igualdad aprenderaprogramar.com
public class TestCompararArrays {
public static void main (String [ ] Args) {
int [ ] miArray1 = {2, -4, 3, -7};
for (int i=0; i<miArray1.length; i++) {
System.out.print ("miArray1[" + i +"]= " + miArray1[i]+"; ");}
System.out.println ("");
int [ ] otroArray = {2, -4, 3, -7};
for (int i=0; i<otroArray.length; i++) {
System.out.print ("otroArray[" + i +"]= " + otroArray[i]+"; ");}
System.out.println ("¿Son el mismo objeto? ... " + (miArray1==otroArray) );
System.out.println ("¿Tienen el mismo contenido (relación de igualdad)? ... " + Arrays.equals(miArray1,
otroArray) );
otroArray = miArray1; //otroArray pasa a ser el mismo objeto que miArray1
for (int i=0; i<otroArray.length; i++) { System.out.print ("otroArray[" + i +"]= " + otroArray[i]+"; "); }
System.out.println ("¿Son el mismo objeto? ... " + (miArray1==otroArray) );
System.out.println ("¿Tienen el mismo contenido (relación de igualdad)? ... " + Arrays.equals(miArray1,
otroArray) );
} //Cierre del main
} //Cierre de la clase
Trata de predecir tú mismo el resultado y compáralo con el que ofrecemos. Resultado:
miArray1[0]= 2; miArray1[1]= -4; miArray1[2]= 3; miArray1[3]= -7;
otroArray[0]= 2; otroArray[1]= -4; otroArray[2]= 3; otroArray[3]= -7; ¿Son el mismo objeto? ...
false
¿Tienen el mismo contenido (relación de igualdad)? ... true
otroArray[0]= 2; otroArray[1]= -4; otroArray[2]= 3; otroArray[3]= -7; ¿Son el mismo objeto? ...
true
¿Tienen el mismo contenido (relación de igualdad)? ... true
El resultado ahora sí es correcto, porque hemos usado correctamente la clase Arrays para
realizar la comparación entre dos arrays.
EJERCICIO EJEMPLO RESUELTO 4. COPIAR CONTENIDOS ENTRE ARRAYS
SIN ESTABLECER RELACIÓN DE IDENTIDAD ( “manual”, aplicable a tipos
primitivos y a objetos).
Antes vimos cómo asignar el contenido de un array a otro haciendo que la variable apunte
al mismo objeto. Vamos a ver ahora cómo copiar el contenido entre dos arrays pero
manteniendo que cada variable denominadora del array apunte a un objeto diferente:
import java.util.Arrays;
//Test copia arrays con igualdad sin identidad aprenderaprogramar.com
public class TestCopiaConIgualdadSinIdentidad {
public static void main (String [ ] Args) {
int [ ] miArray1 = {2, -4, 3, -7};
for (int i=0; i<miArray1.length; i++) {
System.out.print ("miArray1[" + i +"]= " + miArray1[i]+"; ");}
System.out.println();
int [ ] otroArray = {1, 2, 4, 8};
for (int i=0; i<otroArray.length; i++) {
System.out.print ("otroArray[" + i +"]= " + otroArray[i]+"; ");}
System.out.println ("¿Son el mismo objeto? ... " + (miArray1==otroArray) );
System.out.println ("¿Tienen el mismo contenido (relación de igualdad)? ... " +
Arrays.equals(miArray1, otroArray) );
//Realizamos una asignación elemento a elemento
for (int i=0; i < otroArray.length; i++) {
otroArray[i] = miArray1[i];}
for (int i=0; i < otroArray.length; i++) {
System.out.print ("otroArray[" + i +"]= " + otroArray[i]+"; ");}
System.out.println ("¿Son el mismo objeto? ... " + (miArray1==otroArray) );
System.out.println ("¿Tienen el mismo contenido (relación de igualdad)? ... " +
Arrays.equals(miArray1, otroArray) );
} //Cierre del main
} //Cierre de la clase
Trata de predecir tú mismo el resultado y compáralo con el que ofrecemos. Resultado:
miArray1[0]= 2; miArray1[1]= -4; miArray1[2]= 3; miArray1[3]= -7;
otroArray[0]= 1; otroArray[1]= 2; otroArray[2]= 4; otroArray[3]= 8; ¿Son el mismo objeto? ... false
¿Tienen el mismo contenido (relación de igualdad)? ... false
otroArray[0]= 2; otroArray[1]= -4; otroArray[2]= 3; otroArray[3]= -7; ¿Son el mismo objeto? ...
false
¿Tienen el mismo contenido (relación de igualdad)? ... true
EJERCICIO EJEMPLO RESUELTO 5. COPIAR CONTENIDOS ENTRE ARRAYS
SIN ESTABLECER RELACIÓN DE IDENTIDAD (Usando el método copyOf de la
clase Arrays, aplicable a tipos primitivos y a objetos).
El método copyOf de la clase Arrays nos permite:
a) Copiar un array manteniendo el número de elementos.
b) Copiar un array agrandando el número de elementos que tiene, quedando los nuevos
elementos rellenos con valores cero o nulos.
c) Copiar un array empequeñeciendo el número de elementos que tiene; los elementos que
no caben en el nuevo array, dado que tiene menor capacidad, se pierden (el array queda
truncado).
copyOf es un método sobrecargado. En el caso de arrays de enteros su signatura es la
siguiente:
static int[ ] copyOf (int[ ] original, int newLength)
Copia el array especificado, truncando o rellenando con ceros (si fuera necesario) de
manera que la copia tenga el tamaño especificado.
Para el resto de tipos primitivos su sintaxis es análoga: Arrays.copyOf (nombreDelArray, n)
siendo n un entero que define la nueva longitud del array (n puede ser mayor, menor o igual
que la longitud del array original). El código de ejemplo sería este (usamos el copyOf sin
variar la longitud del array):
import java.util.Arrays;
//Test uso de copyOf método clase Arrays aprenderaprogramar.com
public class TestUso_copyOf_1 {
public static void main (String [ ] Args) {
int [ ] miArray1 = { 2, -4, 3, -7 };
for (int i=0; i<miArray1.length; i++) {
System.out.print ("miArray1[" + i +"]= " + miArray1[i]+"; ");
}
System.out.println ("");
int [ ] otroArray = { 1, 2, 4, 8 };
for (int i=0; i<otroArray.length; i++) {
System.out.print ("otroArray[" + i +"]= " + otroArray[i]+"; ");
}
System.out.println ("¿Son el mismo objeto? ... " + (miArray1==otroArray) );
System.out.println ("¿Tienen el mismo contenido (relación de igualdad)? ... " + Arrays.equals(miArray1,
otroArray) );
//Copiamos el array utilizando el método copyOf de la clase Arrays
otroArray = Arrays.copyOf(miArray1, miArray1.length);
for (int i=0; i<otroArray.length; i++) {
System.out.print ("otroArray[" + i +"]= " + otroArray[i]+"; "); }
System.out.println ("¿Son el mismo objeto? ... " + (miArray1==otroArray) );
System.out.println ("¿Tienen el mismo contenido (relación de igualdad)? ... " + Arrays.equals(miArray1,
otroArray) );
} //Cierre del main
} //Cierre de la clase
Trata de predecir tú mismo el resultado y compáralo con el que ofrecemos. Resultado:
miArray1[0]= 2; miArray1[1]= -4; miArray1[2]= 3; miArray1[3]= -7;
otroArray[0]= 1; otroArray[1]= 2; otroArray[2]= 4; otroArray[3]= 8; ¿Son el mismo objeto? ... false
¿Tienen el mismo contenido (relación de igualdad)? ... false
otroArray[0]= 2; otroArray[1]= -4; otroArray[2]= 3; otroArray[3]= -7; ¿Son el mismo objeto? ...
false
¿Tienen el mismo contenido (relación de igualdad)? ... true
Hemos comprobado que el método copyOf de la clase Arrays realiza una copia
elemento a elemento entre los contenidos de dos arrays pero no hace que los punteros
apunten al mismo objeto. Prueba a variar la longitud que se le pasa como parámetro al
método copyOf, por ejemplo:
otroArray = Arrays.copyOf(miArray1, miArray1.length+2); //Resto del código igual
otroArray = Arrays.copyOf(miArray1, miArray1.length-2); //Resto del código igual
Comprueba que los resultados son el alargamiento del array y su relleno con ceros, o el
acortamiento con pérdida de los datos (truncamiento) que no caben debido al recorte de la
longitud. En el caso de alargamiento o expansión del array cuando se trata de un array que
no sea de enteros, si son tipos numéricos se rellenan los excedentes con ceros, si son
booleanos se rellenan los excedentes con false, si son char se rellenan de caracteres vacío, y
si son objeto se rellenan los excedentes con null.
RELLENAR UN ARRAY CON UN VALOR U OBJETO. MÉTODO FILL DE LA
CLASE ARRAYS
La clase Arrays tiene un método, denominado fill, sobrecargado, que permite rellenar un
array con un determinado valor u objeto. En el caso de arrays de enteros la signatura es:
static void fill (int[ ] a, int val)
Asigna el valor entero especificado a cada elemento del array de enteros indicado.
En general la sintaxis será: Arrays.fill (nombreDelArray, valor con el que se rellena). El
valor con el que se rellena depende del tipo del array. Por ejemplo, si es un array de tipo
booleano, tendremos que rellenarlo bien con true o bien con false, no podremos rellenarlo
con un tipo que no sea coherente. Ejemplos de uso:
Arrays.fill (resultado, ‘9’); Como rellenamos con un carácter, resultado habrá de ser un
array de caracteres, ya que en caso contrario no habría coincidencia de tipos.
Arrays.fill (permitido, true); Como rellenamos con un true, resultado será un array de
booleanos. De otra manera, no habría coincidencia de tipos. Ejemplo de código:
import java.util.Arrays;
public class TestMetodoFillArrays {
public static void main (String [ ] Args) { //main cuerpo del programa ejemplo
aprenderaprogramar.com
int [ ] miArray = new int[10];
Arrays.fill(miArray, 33);
for (int tmp: miArray) { System.out.print (tmp + ","); } //Recorrido del array con un
for each
} } //Cierre del main y de la clase
Ejecuta el código y comprueba que el resultado es: 33,33,33,33,33,33,33,33,33,33,. Es
decir, el array queda relleno en todos sus elementos con 33.
En caso de que el array tenga contenidos previos al aplicarle el fill, todos sus elementos
quedarán reemplazados por el elemento de relleno. No obstante, hay otro método que
permite especificar los índices de relleno de modo que se pueda preservar parte del
contenido previo del array:
static void fill (int[ ] a, int fromIndex, int toIndex, int val)
Asigna el valor entero especificado a cada elemento del rango indicado para el array
especificado.
6. El arreglo es la más fundamental de la estructura de datos en las ciencias de la
computación. Este tipo de datos simplemente asigna un bloque de memoria a un número
predeterminado de objetos, y permite que el programador acceda a cada objeto de acuerdo a
su lugar en la línea. En Java, también es posible declarar arreglos con múltiples
dimensiones. Un arreglo de dos dimensiones sería, conceptualmente, una cuadrícula de
objetos, con cada uno de éstos accesible por su fila y columna en la cuadrícula.
Paso 1
Abre el Ambiente de Desarrollo Integrado de Java Netbeans (IDE, por sus siglas en inglés).
Paso 2
Haz clic en "Archivo" y "Crear nueva clase". Nombra la clase "TwoDimensionalArray"
cuando se te indique.
Paso 3
Pega el siguiente código dentro de los corchetes del método "main", para definir un arreglo
de dos dimensiones:
Paso 4
Pega lo siguiente en la próxima línea para acceder a la primera columna, segunda fila del
arreglo:
Recuerda que Java empieza a contar desde "0", de modo que la primera columna es la "0",
y la segunda fila es la columna "1".
Paso 5
Pega lo siguiente en la próxima línea para recorrer el arreglo entero:
for(int x = 0; x < matrix.length; x++) { for (int y = 0; y < matrix[x].length; y++) { int
currentCell = matrix[x][y]; } }
7. Una de las cosas que incorporó Java 5 fue el bucle for-each en Java. Esta estructura nos
permite recorrer una Colección o un array de elementos de una forma sencilla. Evitando el
uso de Iteradores o de un bucle for normal.
En este caso nos estamos apoyando en el tamaño del array, con la propiedad length y en
una variable contador, la cual vamos incrementando hasta que llegue a el tamaño del array.
Para recorrer una Colección, una lista en este caso, podríamos hacerlo con un Iterador de la
siguiente forma:
// Añadimos elementos
list.add("Victor");
list.add("Amaya");
list.add("Julio");
El bucle for-each en Javanos permite realizar estas mismas operaciones de una forma muy
sencilla. La estructura del bucle for-each sería de la siguiente forma:
// Añadimos elementos
list.add("Victor");
list.add("Amaya");
list.add("Julio");
for (String nombre: list)
System.out.println(nombre);
Bibliografía
https://www.aprenderaprogramar.com/index.php?
option=com_content&view=article&id=606:la-clase-vector-del-api-java-metodos-
trimtosize-y-ensurecapacity-ejemplo-y-ejercicios-resueltos-
cu00922c&catid=58&Itemid=180
https://www.campusmvp.es/recursos/post/cadenas-mutables-e-inmutables-en-java-cuando-
usar-string-stringbuilder-y-stringbuffer.aspx
https://www.aprenderaprogramar.com/index.php?
option=com_content&view=article&id=641:copiar-y-comparar-arrays-en-java-conceptos-
identidad-e-igualdad-ejercicios-resueltos-ejemplos-cu00675b&catid=68&Itemid=188
https://www.aprenderaprogramar.com/index.php?
option=com_content&view=article&id=642:clase-arrays-del-api-java-metodos-equals-
comparar-copyof-copiar-fill-rellenar-ejemplos-cu00676b&catid=68&Itemid=188
https://techlandia.com/recorrer-arreglos-dimensiones-java-como_254131/
http://lineadecodigo.com/java/bucle-for-each-en-java/