10. Java¶
Elementos básicos en Java
10.1 Lenguaje de programación JAVA¶
10.1.1 Colecciones¶
Collection Framework Hierarchy
Algunos de los interfaces más usados:
- List: admite elementos repetidos y mantiene un orden inicial.
- ArrayList: array redimensionable que aumenta su tamaño según crece la colección de elementos.
- LinkedList: se basa en una lista doblemente enlazada de los elementos, teniendo cada uno de los elementos un puntero al anterior y al siguiente elemento.
La interfaz Iterable ofrece un método con el que podemos obtener un
objeto Iterator para una colección. Este objeto permite iterar por la
colección, accediendo sucesivamente a cada uno de sus elementos. En el
caso de las listas, existe la interfaz ListIterator que nos permite iterar
también hacia atrás. Por ejemplo:
List<Integer> myMarks = new ArrayList();
myMarks.add(7);
myMarks.add(8);
myMarks.add(9);
Iterator it = myMarks.iterator();
Integer n1 = it.next(); // n1 = 7;
while (it.hasNext()) {
System.out.println(it.next()); // Output: 8, 9.
}
10.1.2 Genéricos (tipos parametrizados)¶
Se llaman parametrizados porque el tipo de dato con el que opera la funcionalidad se pasa como parámetro. Pueden usarse en clases, interfaces y métodos, denominándose clases, interfaces o métodos genéricos respectivamente.
En Java, la declaración de un tipo genérico se hace entre
símbolos <>, pudiendo definir uno o más parámetros, por ejemplo:
Los habrá visto en declaraciones de colecciones:
ArrayList<String> lis = new ArrayList<>()
También puedes crear clases que utilicen genericos.
Ejemplo de genérico:
//Definición de una clase genérica que usa dos genéricos
// GenericClass.java file
public class GenericClass<T, K> {
private T g1;
private K g2;
public GenericClass(T g1, K g2) {
this.g1 = g1;
this.g2 = g2;
}
public T getGenericOne() {
return g1;
}
public K getGenericTwo() {
return g2;
}
}
// Main.java file
public class Main{
public static void main(String[] args) throws Exception {
GenericClass<Integer, String> clazz =
new GenericClass<>(1, "generic");
Integer param1 = clazz.getGenericOne();
String param2 = clazz.getGenericTwo();
System.out.println(String.format("Param1 %d - Param2 %s",
param1, param2));
GenericClass<Double, Int> xxx = new GenericClass<>()
}
}
10.1.3 Funciones Lambda¶
Las lambdas fueron introducidas a partir de Java 8. No son más que funciones anónimas que nos permiten programar en Java con un estilo más funcional y, en ocasiones, declarativo.
La sintaxis de las funciones lambda:
( tipo1 param1, tipoN paramN) -> { cuerpo de la lambda }
(param1, param2) -> { cuerpo }
param1 -> { cuerpo }
() -> { cuerpo }
numero -> String.valueOf(numero)
10.1.3.1 Procesamiento de colecciones con stream¶
En el siguiente ejemplo como para los métodos filter y map
List<String> nombres = Arrays.asList("Ana", "Juan", "Pedro", "Maria", "Luis");
// Filtrar nombres que empiezan con 'M' y convertirlos a mayúsculas
List<String> nombresConM = nombres.stream()
.filter(nombre -> nombre.startsWith("M"))
.map(nombre -> nombre.toUpperCase())
.collect(Collectors.toList());
System.out.println(nombresConM); // Output: [MARIA]
10.1.3.2 Manejo de eventos¶
Por ejemplo con Swing
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class EjemploLambdaSwing {
public static void main(String[] args) {
// Crear el marco de la aplicación
JFrame frame = new JFrame("Ejemplo de Lambda con Swing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
// Crear un panel para contener los componentes
JPanel panel = new JPanel();
// Crear un botón
JButton boton = new JButton("Haz clic aquí");
// Agregar un ActionListener usando una expresión lambda
boton.addActionListener(e -> {
System.out.println("El botón ha sido clicado.");
});
// Agregar el botón al panel
panel.add(boton);
// Agregar el panel al marco
frame.add(panel);
// Hacer visible el marco
frame.setVisible(true);
}
}
10.1.4 Data Processing STREAM¶
Los stream se usan como alternativa al uso de bucles para procesar colecciones desde Java 8.
- Presentan las siguientes características:
- Operaciones fácilmente paralelizables.
- Estilo declarativo de operaciones.
- Concatenación de operaciones en un pipeline.
Para utilizar los streams sobre una colección, basta con invocar al método
stream() o parallelStream(), en función de si queremos paralelizar las
operaciones o no.
Un stream no almacena los valores, sino que se limita a computarlos.
Obtiene los datos de una colección y genera un resultado tras el procesado
de las operaciones intermedias del pipeline mediante una operación
terminal.
Es importante tener en cuenta que las operaciones intermedias devuelven un stream, mientras que las operaciones terminales no. Las operaciones intermedias no se ejecutan hasta que se realiza una operación terminal.
Ejemplo:
ArrayList<Other> l1 = new ArrayList<>();
List<Other> l2 = l1.stream()
.filter(elem -> elem.getAge() < 65)
.sorted() // Ordena según la implementación de Comparable
.map(elem -> new Other(elem.getName,() elem.getAge()))
.collect(toList());
- Filtrado.
- Búsqueda.
- Mapeado.
- Matching.
- Reducción.
- Iteración
Puedes encontrar un listado completo de las operaciones soportadas por los streams en la interfaz java.util.stream.Stream.
Podemos crear stream en otros tipos de datos:
Para convertir un archivo en un stream de líneas, podemos utilizar
Files.lines() como en el siguiente ejemplo:
long numberOfLines = Files.lines(
Paths.get("yourFile.txt"),
Charset.defaultCharset()
).count();
Para finalizar, es importante aclarar que el método collect() es una operación terminal en los Streams que acepta un parámetro de tipo Collector. Podemos crear estos Collectors utilizando los métodos estáticos proporcionados por la clase Collectors. Dependiendo del tipo de Collector que utilicemos, el tipo de colección resultante (como List, Set, Map, etc.) será diferente.
Es el paso final en una secuencia de operaciones de un Stream que permite recopilar los elementos procesados.
Uso de la Clase Collectors:
- La clase Collectors proporciona métodos de fábrica estáticos que nos permiten crear diferentes tipos de Collectors. Ejemplos comunes incluyen Collectors.toList(), Collectors.toSet(), Collectors.groupingBy(), entre otros.
List<String> nombres = Arrays.asList("Ana", "Juan", "Pedro", "Maria", "Luis");
// Usando collect() para obtener una lista
List<String> listaNombres = nombres.stream()
.filter(nombre -> nombre.startsWith("A"))
.collect(Collectors.toList());
// Usando collect() para obtener un conjunto (Set)
Set<String> conjuntoNombres = nombres.stream()
.filter(nombre -> nombre.length() > 3)
.collect(Collectors.toSet());
10.1.5 E/S (I/O)¶
10.1.5.1 Serializable¶
En Java, el término Serializable se refiere a una interfaz (java.io.Serializable) que marca una clase para que sus objetos puedan ser serializados y deserializados.
La serialización es el proceso de convertir un objeto en una secuencia de bytes, lo que permite almacenar el objeto en un medio de almacenamiento (como un archivo o una base de datos) o transmitirlo a través de una red. La deserialización es el proceso inverso: reconstruir el objeto original a partir de la secuencia de bytes.
Interfaz serializable
La interfaz Serializable es una interfaz marcadora (marker interface), lo que significa que no declara ningún método. Su propósito es indicar al mecanismo de serialización de Java que la clase puede ser serializada.
¿Por Qué Usar Serialización? * Persistencia: Guardar el estado de un objeto para su posterior recuperación. * Comunicación: Enviar objetos a través de redes (por ejemplo, en aplicaciones distribuidas o RMI - Remote Method Invocation). * Caching: Almacenar objetos en caché para mejorar el rendimiento.
Cómo Serializar un Objeto Para serializar un objeto, se utiliza la clase ObjectOutputStream. A continuación se muestra un ejemplo básico:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Persona implements Serializable {
private String nombre;
private int edad;
public Persona(String nombre, int edad) {
this.nombre = nombre;
this.edad = edad;
}
// Getters y setters omitidos para brevedad
public static void main(String[] args) {
Persona persona = new Persona("Juan", 30);
try (FileOutputStream archivo = new FileOutputStream("persona.ser");
ObjectOutputStream salida = new ObjectOutputStream(archivo)) {
salida.writeObject(persona);
System.out.println("Objeto serializado correctamente.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Cómo Deserializar un Objeto
Para deserializar un objeto, se utiliza la clase ObjectInputStream.
Ejemplo: Deserialización de un objeto:
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
public class LeerPersona {
public static void main(String[] args) {
try (FileInputStream archivo = new FileInputStream("persona.ser");
ObjectInputStream entrada = new ObjectInputStream(archivo)) {
Persona persona = (Persona) entrada.readObject();
System.out.println("Nombre: " + persona.getNombre());
System.out.println("Edad: " + persona.getEdad());
} catch (Exception e) {
e.printStackTrace();
}
}
}
10.2 Ejemplos de clases¶
- Simple Snake
Como usar librerias usando JFreeChart y lo mismo con Eclipse: https://jfree.github.io/Eclipse-JFreeChart/
y usando maven: https://stackoverflow.com/questions/30964344/adding-jfreechart-to-maven-in-eclipse
10.2.1 Juego de la vida¶
https://es.m.wikipedia.org/wiki/Juego_de_la_vida y más general : https://es.m.wikipedia.org/wiki/Aut%C3%B3mata_celular
10.2.2 la hormiga de Langton¶
- En el Pais
10.3 Librerias Java¶
10.3.1 Librerias de tod¶
- Apache common. Con multiples librerias, por ejemplo:
- CSV para lectura escritura de formatos cvs
- CLI Command line
- NET, utilidades de red
- Hibernate para base de datos
10.3.2 Servidores de juegos¶
- java game server
- LWJG Libreria para juegos.
- LITIENGINE
10.4 GRAFICOS¶
10.4.1 Librerias¶
10.4.2 Chart¶
Para empezar este hilo de stackoverflow * Tutorial JFreechart * Charts4j * jzy3d *