3. UNIDAD 3. CONCEPTOS AVANZADOS
Continuación de mapas
NOTAS:
Los mapas tienen la estructura implícita basada en árboles.
En realidad se puede prescindir de los iteradores para los mapas pues tienen una clave
asociada al objeto y se les puede buscar por ésta.
Los mapas más importantes y útiles son:HashMap, TreeMap y LinkedHashMap.
HashMap: Los elementos que inserta en el map no importa el orden. No aceptan claves
duplicadas ni valores nulos.
TreeMap: Orden de forma natural.
LinkedHashMap: Inserta los elementos en el orden en el que van llegando, no tiene un
ordenamiento de los elementos. Esta clase realiza las búsquedas de los elementos de forma
más lenta que los demás.
4. UNIDAD 3. CONCEPTOS AVANZADOS
Continuación de mapas
Ejemplo 1:
//HashMap con clave "Integer" y Valor "String".
Map<Integer, String> nombreMap = new HashMap<Integer, String>();
nombreMap.size(); // Devuelve el numero de elementos del Map
nombreMap.isEmpty(); // Devuelve true si no hay elementos
nombreMap.put(K clave, V valor); // Añade un elemento al Map
nombreMap.get(K clave); // Devuelve la clave o 'null' si la clave no existe
nombreMap.clear(); // Borra todos los componentes del Map
nombreMap.remove(K clave); // Borra el par clave/valor
nombreMap.containsKey(K clave); // Devuelve true si hay una clave que coincide con K
nombreMap.containsValue(V valor); // Devuelve true si hay un Valor que coincide con V
nombreMap.values(); // Devuelve una "Collection" con los valores del mapa
8. UNIDAD 3. CONCEPTOS AVANZADOS
Continuación de mapas
Ejemplo 4: Recorrido con forEach:
. . .
for (Entry<Integer, String> it: map.entrySet()){
Integer clave = it.getKey();
String valor = it.getValue();
System.out.println(clave+" -> "+valor);
}
9. UNIDAD 3. CONCEPTOS AVANZADOS
Tipos de datos abstractos: Pila (Stack)
Lista ordenada tipo LIFO (Last In First Out) que permite agregar y eliminar objetos.
Siempre se tiene acceso al elemento que se introdujo al últilmo, el cual se llama TOS: Top Of
Stack.
Se utilizan preferentemente en:
Evaluación de expresiones en notación polaca inversa, es decir, posfija.
Evaluación sintáctica en algunos lenguajes independientes del contexto.
Al realizar recursividad.
Sus métodos principales son: push() y pop() para agregar y eliminar elementos en ella.
10. UNIDAD 3. CONCEPTOS AVANZADOS
Tipos de datos abstractos: Pila (Stack)
Ejemplo:
public class StackTest{
public static void main(String args[]) {
Stack st = new Stack();
st.push(“elementos");
st.push(“de");
st.push(“ejemplo");
System.out.println(“Se borra el primer elemento: "+st.pop());
System.out.println(" despues de borrarlo : "+st);
}
}
11. UNIDAD 3. CONCEPTOS AVANZADOS
Tipos de datos abstractos: Cola (Queue)
Secuencia de elementos en la que se insertan objetos por un lado y se eliminan por el otro. Su
orden es FIFO, First In First Out.
Se utilizan preferentemente en:
Sistemas de cómputo.
Sistemas de transporte.
Procesamiento de datos donde debe cumplir esta característica
Se utilizan en conjunto con listas ligadas (LinkedList). Sus métodos son: offer() y add() para
insertar objetos, remove() y poll() para sacar elementos, element() y peek() para tomar el primer
elemento.
12. UNIDAD 3. CONCEPTOS AVANZADOS
Tipos de datos abstractos: Cola (Queue)
public class Main {
public static void main(String[] args) {
Queue<Integer> cola=new LinkedList();
cola.offer(21);
cola.add(4);
cola.offer(2);
cola.add(5);
cola.offer(11);
System.out.println(“datos de Cola: " + cola);
while(cola.poll()!=null){//Desencolamos y el valor se compara con null
System.out.println(cola.peek());//Muestra el nuevo primer valor
}
System.out.println(cola.peek()); //Muestra null, la cola ya esta vacia
}
}
13. UNIDAD 3. CONCEPTOS AVANZADOS
Tipos de datos abstractos: Cola (Queue)
Otro ejemplo:
public class Main {
public static void main(String[] args) {
Queue<Persona> cola = new LinkedList<Persona>();
cola.add(new Persona(“Ivan", 4));
cola.add(new Persona(“Gerardo", 3));
cola.add(new Persona(“David", 2));
cola.add(new Persona(“Brenda", 1));
while (!cola.isEmpty()) {
Persona p = cola.remove();
System.out.println(p.getNombre() " " + p.getId());
}
}
}
14. UNIDAD 3. CONCEPTOS AVANZADOS
EJERCICIO. Cola y Pila
Utilizar la clase Libreta (atributos: marca, número de hojas, tamaño color y precio).
Crear una cola de 5 libretas y prueba todos los métodos de ésta.
Crear una pila de 6 libretas y prueba todos los métodos de ésta.
También crea un mapa de libretas con una clave (key) de tipo String, prueba todos los
métodos de un mapa. Elige un tipo de mapa en particular.
15. UNIDAD 3. CONCEPTOS AVANZADOS
Flujos de datos: Streams
Los flujos o streams son utilizados para almacenar los datos de entrada y salida desde el
teclado, una red o un archivo.
Las instrucciones para leer y escribir comunes en Java son:
System. out.println(“Mostrado en pantalla”);
System.in.read();
(Y a partir de Java 6 se utiliza la clase Scanner).
Los flujos estándar de entrada y salida están abiertos mientras se ejecuta el programa, listos
para proporcionar datos (entrada) o para dar datos (salida).
Por defecto, el flujo estándar de entrada es el teclado. (System.in)
Por defecto, el flujo estándar de salida es la pantalla. (System.out)
16. UNIDAD 3. CONCEPTOS AVANZADOS
Flujos de datos: Streams
Los flujos ayudan a controlar el intercambio de información entre un programa y los
dispositivos de almacenamiento o de comunicación. Los datos de entrada y de salida pueden
ser arreglos de bytes, un archivo, los tubos, bases de datos, etc.
Java distingue:
Flujos de caracteres o de bytes
Flujos de entrada y salida
Flujos que inician y los que son secundarios.
Datos de
entrada
Programa
Datos de
salida
17. UNIDAD 3. CONCEPTOS AVANZADOS
Streams: Archivos
En Java se puede crear, leer y escribir archivos. Esto requiere también el manejo de varias
excepciones.
Se utiliza la clase File para crear objetos de tipo archivo.
Y las clases FileWriter y FileReader para su escritura y lectura, respectivamente.
Sintaxis:
File fichero = new File(ruta/archivo);
NOTA: El uso de las diagonales depende del sistema operativo, puede ser:
// / ó
O también se puede utilizar el separador que trae por default la clase File:
File.separator
18. UNIDAD 3. CONCEPTOS AVANZADOS
Streams: Archivos
Algunos de sus métodos son:
getName(): Nombre del archivo
getAbsolutePath(): Se obtiene la ruta absoluta de un archivo
exists(): Pregunta si ya existe el archivo
canRead(): pregunta si se tienen permisos de lectura en el archivo
canWrite(): pregunta si se tienen permisos de escritura en el archivo
lastModified(): Indica cuando fue la última modificación
delete(): Borra el archivo
createNewFile(): Permite crear un nuevo archivo
mkdir(): Permite crear un nuevo directorio
19. UNIDAD 3. CONCEPTOS AVANZADOS
Streams: Archivos de escritura
Ejemplo de escritura sin tipo de codificación:
public static void main(String[] args) {
String[] lineas = { “Anillo", “Burro", “Calcio", “Dedo", “Elefante"};
FileWriter arch = null;
try {
arch = new FileWriter(“arch_prueba.txt"); //si no existe lo crea
// Escribimos linea a linea en el archivo
for (String line : lineas) { //con forEach
arch.write(line + "n");
}
arch.close();
} catch (Exception e) {
System.out.println("excepción: " + e.getMessage());
}
}
20. UNIDAD 3. CONCEPTOS AVANZADOS
Streams: Archivos de escritura
Ejemplo de escritura con tipo de codificación UTF-8:
public static void main(String[] args) {
String[] lineas = { “Anillo", “Burro", “Calcio", “Dedo", “Elefante"};
Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(“arch2.txt"), "UTF-8"));
// Escribimos linea a linea en el fichero
for (String linea : lineas) {
try {
out.write(linea+"n");
}catch (IOException ex){ System.out.println("excepcion: " + ex.getMessage());
} catch (UnsupportedEncodingException | FileNotFoundException ex2) {
System.out.println("error 2: " + ex2.getMessage());
} finally {
out.close();
}
}
21. UNIDAD 3. CONCEPTOS AVANZADOS
Streams: Archivos de lectura
Ejemplo:
File arch= new File("arch1.txt"); // Fichero del que queremos leer
Scanner s = null;
try {
s = new Scanner(arch); // Leemos el contenido del archivo
while (s.hasNextLine()) { // Leemos linea a linea el archivo
String linea = s.nextLine(); // Guardamos la linea en un String
System.out.println(linea); // Imprimimos la linea
}
} catch (Exception e) { System.out.println("error " + e.getMessage());
} finally {
try {
if (s != null)
s.close();
} catch (Exception e2) {
System.out.println("error : " + e2.getMessage());
} }
22. UNIDAD 3. CONCEPTOS AVANZADOS
Streams: Archivos
Ejemplo desde un archivo:
try{
FileInputStream fis = new FileInputStream(“persona.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
a1 = (Persona) ois.readObject();//El método readObject() recupera el objeto
a2 = (Persona) ois.readObject();
ois.close(); fis.close();
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}catch(ClassNotFoundException e){
e.printStackTrace();
}
23. UNIDAD 3. CONCEPTOS AVANZADOS
Streams binarios y de texto
Los dos tipos principales son: Los binarios y de texto.
Los flujos binarios se encuentran en la clase: ByteStream, de la cual surgen:
InputStream ( read() ) y OutputStream ( write(int b) ).
Los flujos de texto trabajan con código unicode y se encuentran en la clase: CharacterStream, de la
cual surgen:
Reader ( read(char[] b,int o,int l) ) y Writer( write(char[] b,int o,int l) )
26. UNIDAD 3. CONCEPTOS AVANZADOS
InputStream y OutputStream
Clases abstractas que definen el comportamiento mínimo de estos flujos.
Lanza la excepción IOException si hay error.
Métodos de InputStream:
int read(): lee un byte y lo devuelve como int
int read(byte[] buf): lee varios bytes y los guarda en buffer
int read(byte[] buf, int offset, int count): devuelve -1 si se lee nada
Métodos de OutputStream:
void write(int buf): Escribe lo que tiene en el buffer en tipo entero
void write(byte[] buf): Escribe lo que tiene en el buffer en tipo byte
void write(byte[] buf, int offset, int count) Escribe lo que tiene en el buffer tipo byte
void flush(); // descarga el buffer
27. UNIDAD 3. CONCEPTOS AVANZADOS
Streams:FileInputStream y FileOutputStream
Permite trabajar con archivos manipulados por flujos. Se produce un FileNotFoundException
Ej:
FileInputStream a = null;
FileOutputStream b = null;
try {
a= new FileInputStream(args[0]);
b= new FileOutputStream(args[1]); // Copia de los bytes
int i = a.read();
while (i != -1) { // -1 si se alcanza el fin de fichero
b.write(i);
i = a.read();
}
a.close();
b.close();
} catch (ArrayIndexOutOfBoundsException e) { System.err.println(“Sale del rango ");
} catch (FileNotFoundException e) { System.err.println("No se encontro el archivo“ + e);
} catch (IOException e) { System.err.println("Error de Entrada o salida“ + e); }
28. UNIDAD 3. CONCEPTOS AVANZADOS
Streams: Filtros
FilterInputStream y FilterOutputStream. Proporcionan funcionalidad adicional a los flujos
normales reescribiendo los métodos correspondientes.
DataInputStream y DataOutputStream. Permiten que las aplicaciones puedan leer y escribir
datos de tipos simples de Java desde/sobre el flujo que envuelven. Se deben utilizar ambos.
BufferedInputStream y BufferedOutputStream. Proporcionan eficiencia en lectura y escritura.
29. UNIDAD 3. CONCEPTOS AVANZADOS
Streams: Filtros
public static void main(String args[]) throws IOException {
FileOutputStream gdF = new FileOutputStream("datos.dat");
DataOutputStream dosF = new DataOutputStream(gdF); // Escribimos algunos datos
dosF.writeBoolean(true);
dosF.writeChar('A');
dosF.writeByte(Byte.MAX_VALUE);
dosF.writeInt(Integer.MAX_VALUE);
dosF.writeDouble(Double.MAX_VALUE);
dosF.close(); // Cerramos el flujo. Cierra todos
// Creamos un flujo de entrada de datos
FileInputStream ldF = new FileInputStream("datos.dat");
DataInputStream disF = new DataInputStream(ldF); // Leemos los datos guardados
boolean v = disF.readBoolean();
char c = disF.readChar();
byte b = disF.readByte();
int i = disF.readInt();
double d = disF.readDouble(); // Cerramos el flujo disF.close(); // cierra todo // Mostramos los datos System.out.println(v);
System.out.println(c); System.out.println(b); System.out.println(i); System.out.println(d); }
30. UNIDAD 3. CONCEPTOS AVANZADOS
Streams: Otros flujos
ByteArrayInputStream
ByteArrayOutputStream (para leer o escribir sobre un buffer o arreglo de bytes)
PipedInputStream
PipedOutputStream (para establecer un flujo de datos entre distintas hebras)
SequenceInputStream (para encadenar/secuenciar varios flujos de entrada)
31. UNIDAD 3. CONCEPTOS AVANZADOS
Streams de caracteres: Reader y Writer
Métodos de Reader:
int read()
int read(char[] b)
int read(char[] b, int off, int len); // devuelve -1 si no hay qué leer
long skip(long n)
Métodos de Writer:
void write(int b)
void write(char[] b)
void write(String s)
void write(char[] b, int off, int len);
void write(String s, int off, int len);
void flush()
32. UNIDAD 3. CONCEPTOS AVANZADOS
Streams de caracteres: Reader y Writer
Java lee y escribe caracteres con UNICODE
Cada plataforma trabaja con un código específico pero puede configurarse
Reader requiere de InputStreamReader como descodificador de bytes a caracteres
Writer requiere de OutputStreamWriter para codificar los caracteres a bytes
33. UNIDAD 3. CONCEPTOS AVANZADOS
EJERCICIO. Streams
Utilizar la clase Persona que se ha creado en ejercicios anteriores.
Crear un archivo de texto que contenga los nombres y apellidos de 5 personas.
Utilizar alguno de los flujos para agregar más datos de dos personas al archivo, eliminar la
primer línea y leer el mismo para mostrar los resultados, es decir, el archivo original y el
archivo después de la eliminación y la agregación.
34. UNIDAD 3. CONCEPTOS AVANZADOS
Persistencia: Serialización
Serializable es una interfaz que guarda el estado del objeto tal y como lo mantenemos en la
ejecución del programa.
La serialización de un objeto consiste en obtener una trama de bytes que represente
el estado de un objeto,(donde podrá ser escrito dentro de un archivo o enviado a través de
una red) haciendo posible la persistencia de objetos.
La persistencia es el estado de un objeto que se almacena para su uso posterior.
Si se desea exceptuar un atributo del objeto que no vamos a serializar se utiliza el
modificador Transient. Este le indica a la JVM que dicho atributo será ignorado ewn la
serialización.
Los atributos con modificador static nunca se serializan en un objeto, ya que este atributo
pertenece a la clase y no al objeto.
35. UNIDAD 3. CONCEPTOS AVANZADOS
Persistencia: Serialización
Ejemplo:
public class Persona implements Serializable{
private String nombre;
private String apPaterno;
private transient String apMaterno;
…
public Persona (String nombre, String apPaterno, String apMaterno){
this.nombre = nombre;
this.apPaterno = apPaterno;
this.apMaterno = apMaterno;
}
}
No se serializará
36. UNIDAD 3. CONCEPTOS AVANZADOS
Persistencia: Serialización
Ejemplo en un archivo:
public static void main(String[] args){
Persona a1 = new Persona("Juan", "Salinas", "Diaz");
Persona a2 = new Persona("Elia", "Medina", "Medrano");
try{
FileOutputStream fs = new FileOutputStream("persona.txt");//Creamos el archivo
ObjectOutputStream os = new ObjectOutputStream(fs);//Tiene el método writeObject()
os.writeObject(a1);//El método writeObject() serializa el objeto y lo escribe en el archivo
os.writeObject(a2);
os.close();//Hay que cerrar siempre el archivo
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
37. UNIDAD 3. CONCEPTOS AVANZADOS
Persistencia: Serialización
Si dentro de una clase hay atributos que son otras clases, también deben ser Serializable.
Con los wrappers no hay problema porque por defecto lo son. Si ponemos como atributos
nuestras propias clases, éstas a su vez deben implementar Serializable.
Ej:
public class Persona implements Serializable{
private String nombre;
private String apPaterno;
private String apMaterno;
private Fecha fechaNacimiento; //Debe ser serializable también
…
}
38. UNIDAD 3. CONCEPTOS AVANZADOS
Persistencia: Conversión entre serializable y bytes
Podemos convertir cualquier objeto Serializable a un arreglo de bytes y viceversa utilizando los
flujos como por ejemplo, ObjectInputStream y ObjectOutputStream
Ejemplo de objeto a bytes:
ByteArrayOutputStream bs= new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream (bs);
os.writeObject(unObjetoSerializable); // this es de tipo DatoUdp os.close();
byte[] bytes = bs.toByteArray(); // devuelve byte[]
Ejemplo de bytes a objeto:
ByteArrayInputStream bs= new ByteArrayInputStream(bytes); // bytes es el byte[]
ObjectInputStream is = new ObjectInputStream(bs);
ClaseSerializable unObjetoSerializable = (ClaseSerializable)is.readObject();
is.close();
39. UNIDAD 3. CONCEPTOS AVANZADOS
Persistencia: Serial Version UID
Cuando se serializa, ambos lados (el que envía y el que recibe la clase) tienen su propia copia
del archivo en código de bytes (.class) creando inconsistencia entre las copias, por lo tanto, se
tienen diferentes versiones. Si esto llega a suceder, la codificación/decodificación de los datos
de la clase no se puede realizar.
Para ello se crea el atributo:
private static final long serialVersionUID = 2789756448674416218L;
Cada que se compile el número debe ser diferente para que Java identifique cada versión.
40. UNIDAD 3. CONCEPTOS AVANZADOS
Persistencia: JPA
JPA: Java Persistence API: Es un modelo de persistencia que permite mapear objetos
particulares en bases de datos relacionales.
Se puede utilizar en aplicaciones web y stand alone.
Se combina con el uso de frameworks de persistencia como Hibernate, Toplink y JDO.
La relación entre entidades de Java y tablas de bases de datos se realiza por anotaciones en
las propias clases.
Se utiliza notación XML para manejar la persistencia de esta manera
41. UNIDAD 3. CONCEPTOS AVANZADOS
PRÁCTICA GENERAL: Persistencia
Utilizar el archivo creado en el ejercicio de clase y la clase Persona (asegurarse que tenga como
atributos: nombre, apellido paterno, apellido materno, edad, estado civil).
Serializar la clase.
Los atributos que no se deben de serializar son edad y estado civil
Mandar estos datos a un archivo
Solicitar que se introduzcan datos de una persona desde el teclado con la clase Scanner y guardarlos en
el archivo. Los datos a solicitar sólo son su nombre y apellidos.
Estos datos se deben ir almacenando en un archivo
Mostrar los datos al final