java
java
Métodos en Java
Tipos de métodos en Java
Declaración de métodos
Llamada de métodos
Estructuras de datos Java
ArrayList
Declaración
Metodos
Ejemplos Aplicados
Añadir Elementos:
Acceder a Elementos:
Eliminar Elementos
Tamaño y Capacidad
Buscar Elementos
Convertir a Array
Operaciones Avanzadas
Hashtable
Características Principales:
Puntos Clave:
Consideraciones:
java.util.Random
java.lang.Math
java.util.concurrent.ThreadLocalRandom
java.security.SecureRandom
Usando HashTable
put(K key, V value)
Usando JOptionPane
showMessageDialog (Component parentComponent, Object message)
String showInputDialog(Object message)
showConfirmDialog
Combo JOptionPane
¿Qué es la programación orientada a objetos?
¿Por qué la programación orientada a objetos?
Clases y objetos
¿Qué son las clases y los objetos?
Clases en Java
Esqueleto de una clase
Modificadores de acceso
Métodos getter y setter
Paradigmas de la POO
Encapsulamiento
Abstracción
Herencia
Super()
Invocar el Constructor de la Clase Base
Acceder a Métodos y Variables de la Clase Base
Puntos Clave
Aplicando herencia caso BetPlay
Polimorfismo
Ejemplo de Sobrecarga de Métodos en Java
Ejemplo de Sobrescritura de Métodos en Java
Test Conocimiento
Patrones de diseño
SOLID
S - Single Responsibility Principle (SRP)
Mal diseño
Buen diseño (siguiendo el SRP)
O - Open/Closed Principle (OCP)
Mal diseño (violación del OCP)
Beneficios del OCP
L - Liskov Substitution Principle (LSP)
Beneficios del LSP
I - Interface Segregation Principle (ISP)
Mal diseño (violación del ISP)
Buen diseño (siguiendo el ISP)
Beneficios del ISP
D - Dependency Inversion Principle (DIP)
Mal diseño (violación del DIP)
Buen diseño (siguiendo el DIP)
Resumiendo....
Problema
Aplicando Principios SOLID
Principio de Responsabilidad Única (SRP)
Aplicando Principios SOLID
Principio de Responsabilidad Única (SRP)
Principio de Abierto/Cerrado (OCP)
Principio de Sustitución de Liskov (LSP)
Principio de Segregación de Interfaces (ISP)
Principio de Inversión de Dependencias (DIP)
Persistencia de Datos (Mysql)
¿Qué es JDBC?
Componentes Principales de JDBC
Configuración de controlador (MySQl)
Expresiones Lambda
Características de las Expresiones Lambda
Sintaxis de una Expresión Lambda
Ejemplos de Expresiones Lambda
Sin Parámetros:
Con un Parámetro:
Con Múltiples Parámetros:
Bloque de Código:
Uso de Expresiones Lambda
Iterar sobre una colección:
Explicación del Código
Ordenar Usando Comparator con Expresión Lambda
Consumer
Características de Consumer
Uso de Consumer con Expresiones Lambda
Ejemplo: Uso de Consumer con Expresiones Lambda
BiConsumer
Características de BiConsumer
Sintaxis de BiConsumer
Ejemplo de Uso de BiConsumer con Expresiones Lambda
Ejemplo: Procesar Pares Clave-Valor
Supplier
Características de Supplier
Sintaxis de Supplier
Ejemplo: Generar un Valor Aleatorio
Ejercicio:
Explicación del Código
Predícate
Características de Predicate
Métodos Comunes en Predicate
Sintaxis de una Expresión Lambda que Implementa Predicate
Ejemplos de Uso
1. Ejemplo Básico con Predicate
Explicación del Código
2. Ejemplo con Listas y Predicate
Explicación del Código
3. Combinación de Predicados
Explicación del Código
Ejemplo Completo con la Clase Persona
Stream
Características de los Streams
Componentes Principales de los Streams
Ejemplo Básico de Uso de Streams
Operaciones Comunes en Streams
1. filter
2. map
3. collect
4. forEach
5. reduce
Ejemplo Completo con la Clase Persona
Generar Ejecutable
Instalar en linux
Instalar maven windows
Probar configuracion de maven
Configuración del proyecto en Visual Studio Code
Mutabilidad
La mutabilidad se refiere a la capacidad de un objeto de cambiar su estado después de su
creación. En el contexto de programación, un objeto mutable es aquel cuyos valores internos
pueden ser modificados después de la creación del objeto. Un objeto inmutable no puede
cambiar su estado cuando se ha creado.
package com.trainer.mutabilidad;
Clases envolventes (Wrapper classes): Las clases como Integer, Double, etc., son inmutables.
Métodos en Java
Los métodos en Java son secciones de código diseñadas para ejecutar tareas específicas,
identificados por un nombre y capaces de recibir parámetros que les proporcionan la información
necesaria. Estos parámetros actúan como datos de entrada para el método, permitiéndole operar
con los valores recibidos.
Dentro del cuerpo del método, se pueden llevar a cabo diversas acciones, como operaciones
matemáticas, manipulación de datos o incluso llamadas a otros métodos. Una vez que el método
ha completado su tarea, puede devolver un resultado mediante la palabra clave "return" seguida
del valor deseado.
La capacidad de reutilización del código es una de las principales ventajas de los métodos en Java.
Al definir un método una vez, podemos invocarlo en diferentes partes del programa, evitando la
repetición innecesaria de código. Esto no solo simplifica la estructura del código, sino que también
facilita su mantenimiento y promueve un mayor modularidad en la aplicación.
· Métodos de retorno: Estos métodos entregan un valor al finalizar su ejecución. Este valor
puede ser de cualquier tipo de dato válido en Java, como números enteros, cadenas de texto,
booleanos, entre otros. Por ejemplo, podría ser el resultado de una operación aritmética.
· Métodos estáticos: Los métodos estáticos están asociados a la clase en lugar de una instancia
de la clase. Estos métodos se pueden invocar directamente sin la necesidad de crear un objeto.
Declaración de métodos
Llamada de métodos
Estructuras de datos Java
ArrayList
La clase ArrayList en Java permite almacenar datos en memoria de manera similar a los Arrays,
pero con la ventaja de que puede ajustar dinámicamente la cantidad de elementos almacenados,
eliminando la necesidad de declarar su tamaño previamente, como ocurre con los Arrays.
Declaración
Ejemplo
Metodos
1. Añadir Elementos:
2. Acceder a Elementos:
3. Eliminar Elementos:
4. Tamaño y Capacidad:
5. Buscar Elementos:
6. Convertir a Array:
Object[] toArray() : Devuelve un array que contiene todos los elementos de la lista
en el orden adecuado.
<T> T[] toArray(T[] a) : Devuelve un array que contiene todos los elementos de la
lista en el orden adecuado; el tipo del array devuelto es del mismo tipo que el array
especificado.
7. Operaciones Avanzadas:
8. Clonación y Comparación:
9. Iteración:
Ejemplos Aplicados
Añadir Elementos:
boolean add(E e)
package com.trainer.mutabilidad;
import java.util.ArrayList;
método añade "Backend Java" al final del ArrayList . La salida muestra que el ArrayList ahora
contiene un elemento.
package com.trainer.mutabilidad;
import java.util.ArrayList;
Acceder a Elementos:
get(int index)
package com.trainer.mutabilidad;
import java.util.ArrayList;
Este método reemplaza el elemento en una posición especifica (list.set(0, "Programacion web");)
package com.trainer.mutabilidad;
import java.util.ArrayList;
Eliminar Elementos
package com.trainer.mutabilidad;
import java.util.ArrayList;
package com.trainer.mutabilidad;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Backend ");
list.add(0, "Fundamentos");
String elemento = list.get(0);
System.out.println(elemento);
list.set(0, "Programacion web");
String eliminado = list.remove(1);
System.out.println(eliminado);
//--------------------------
list.add("Pasteleria");
boolean result = list.remove("Pasteleria");
//--------------------------
System.out.println(result);
System.out.println(list);
}
}
void clear() método elimina todos los elementos del ArrayList , dejándolo vacío.
package com.trainer.mutabilidad;
import java.util.ArrayList;
Tamaño y Capacidad
package com.trainer.mutabilidad;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Backend ");
list.add(0, "Fundamentos");
String elemento = list.get(0);
System.out.println(elemento);
list.set(0, "Programacion web");
String eliminado = list.remove(1);
System.out.println(eliminado);
list.add("Pasteleria");
boolean result = list.remove("Pasteleria");
System.out.println(result);
System.out.println(list);
//------------------------------------
int size = list.size();
System.out.println(size); // Output: 2
//-----------------------------------
System.out.println(list);
}
}
boolean isEmpty() Este método devuelve true si el ArrayList está vacío, de lo contrario
devuelve false .
package com.trainer.mutabilidad;
import java.util.ArrayList;
package com.trainer.mutabilidad;
import java.util.ArrayList;
int indexOf(Object o) Este método devuelve el índice de la primera ocurrencia del elemento a
buscar. Si no se encuentra el elemento retorna -1
package com.trainer.mutabilidad;
import java.util.ArrayList;
package com.trainer.mutabilidad;
import java.util.ArrayList;
package com.trainer.mutabilidad;
import java.util.*;
import java.util.ArrayList;
Operaciones Avanzadas
boolean addAll(Collection<? extends E> c) Este método añade todos los elementos de
otraLista al final del ArrayList original.
package com.trainer.mutabilidad;
import java.util.*;
boolean addAll(int index, Collection<? extends E> c) Este método inserta todos los
elementos de otraLista en la posición 2 del ArrayList original.
package com.trainer.mutabilidad;
import java.util.*;
package com.trainer.mutabilidad;
import java.util.*;
package com.trainer.mutabilidad;
import java.util.*;
Hashtable
Las Hashtable en Java son una estructura de datos que implementa una tabla hash, la cual
permite almacenar pares de clave-valor y ofrece una manera eficiente de buscar valores
asociados a claves específicas. La clase Hashtable es parte del paquete java.util .
Características Principales:
1. Sincronización: Hashtable es sincronizada, lo que significa que es segura para su uso en
entornos multi-hilo. Sin embargo, esta sincronización puede afectar el rendimiento
comparado con colecciones no sincronizadas como HashMap .
2. No permite null : No permite claves ni valores null . Intentar insertar null como clave o
valor resultará en una excepción NullPointerException .
4. Comprobar Existencia:
Clave: hashtable.containsKey(2);
Valor: hashtable.containsValue("Cereza");
Consideraciones:
Uso en Aplicaciones Concurrentes: Debido a su naturaleza sincronizada, Hashtable puede
ser útil en aplicaciones donde múltiples hilos acceden y modifican la estructura de datos
simultáneamente.
java.util.Random
La clase Random es una de las formas más comunes y flexibles para generar números aleatorios.
import java.util.Random;
java.lang.Math
public class MathRandomExample {
public static void main(String[] args) {
// Generar un número doble aleatorio entre 0.0 y 1.0
double randomDouble = Math.random();
System.out.println("Número doble aleatorio entre 0.0 y 1.0: " +
randomDouble);
java.util.concurrent.ThreadLocalRandom
La clase ThreadLocalRandom es recomendada para generar números aleatorios en entornos
multi-hilo.
import java.util.concurrent.ThreadLocalRandom;
import java.security.SecureRandom;
Usando HashTable
put(K key, V value)
package com.creativecode.hashtable;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
import com.creativecode.hashtable.StaticClass.Variables;
@SuppressWarnings("unused")
int valueNumber= 0;
Hashtable <Integer,String> personas = new Hashtable<>();
Variables.uniqueNumbers = new HashSet<>();
} catch (Exception e) {
// TODO: handle exception
}
}
public static int GenerateUnique(){
int randomNumber = 0;
randomNumber = ThreadLocalRandom.current().nextInt(Variables.max);
Variables.uniqueNumbers.add(randomNumber);
return randomNumber;
}
}
package com.creativecode.hashtable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
import com.creativecode.hashtable.StaticClass.Variables;
@SuppressWarnings("unused")
int valueNumber= 0;
Hashtable <Integer,String> personas = new Hashtable<>();
Variables.uniqueNumbers = new HashSet<>();
try (Scanner sc = new Scanner(System.in)){
System.out.println("Ingrese el nombre :");
personas.put(GenerateUnique(), sc.nextLine());
//----------------GET----------------------------------------
System.out.println(personas.get(getLastNumber()));
//-----------------------------------------------------------
} catch (Exception e) {
// TODO: handle exception
}
}
public static int GenerateUnique(){
int randomNumber = 0;
randomNumber = ThreadLocalRandom.current().nextInt(Variables.max);
Variables.uniqueNumbers.add(randomNumber);
return randomNumber;
}
public static int getLastNumber(){
List<Integer> numberList = new ArrayList<>(Variables.uniqueNumbers);
return numberList.get(numberList.size()-1);
}
}
package com.creativecode.hashtable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
import com.creativecode.hashtable.StaticClass.Variables;
@SuppressWarnings("unused")
int valueNumber= 0;
Hashtable <Integer,String> personas = new Hashtable<>();
Variables.uniqueNumbers = new HashSet<>();
}
public static int GenerateUnique(){
int randomNumber = 0;
randomNumber = ThreadLocalRandom.current().nextInt(Variables.max);
Variables.uniqueNumbers.add(randomNumber);
return randomNumber;
}
public static int getLastNumber(){
List<Integer> numberList = new ArrayList<>(Variables.uniqueNumbers);
return numberList.get(numberList.size()-1);
}
}
package com.creativecode.hashtable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
import com.creativecode.hashtable.StaticClass.Variables;
@SuppressWarnings("unused")
int valueNumber= 0;
Hashtable <Integer,String> personas = new Hashtable<>();
Variables.uniqueNumbers = new HashSet<>();
} catch (Exception e) {
// TODO: handle exception
}
}
public static int GenerateUnique(){
int randomNumber = 0;
randomNumber = ThreadLocalRandom.current().nextInt(Variables.max);
Variables.uniqueNumbers.add(randomNumber);
return randomNumber;
}
public static int getLastNumber(){
List<Integer> numberList = new ArrayList<>(Variables.uniqueNumbers);
return numberList.get(numberList.size()-1);
}
}
package com.creativecode.hashtable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
import com.creativecode.hashtable.StaticClass.Variables;
@SuppressWarnings("unused")
int valueNumber= 0;
Hashtable <Integer,String> personas = new Hashtable<>();
Variables.uniqueNumbers = new HashSet<>();
} catch (Exception e) {
// TODO: handle exception
}
}
public static int GenerateUnique(){
int randomNumber = 0;
randomNumber = ThreadLocalRandom.current().nextInt(Variables.max);
Variables.uniqueNumbers.add(randomNumber);
return randomNumber;
}
public static int getLastNumber(){
List<Integer> numberList = new ArrayList<>(Variables.uniqueNumbers);
return numberList.get(numberList.size()-1);
}
}
package com.creativecode.hashtable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
import com.creativecode.hashtable.StaticClass.Variables;
@SuppressWarnings("unused")
int valueNumber= 0;
Hashtable <Integer,String> personas = new Hashtable<>();
Variables.uniqueNumbers = new HashSet<>();
} catch (Exception e) {
// TODO: handle exception
}
}
public static int GenerateUnique(){
int randomNumber = 0;
randomNumber = ThreadLocalRandom.current().nextInt(Variables.max);
Variables.uniqueNumbers.add(randomNumber);
return randomNumber;
}
public static int getLastNumber(){
List<Integer> numberList = new ArrayList<>(Variables.uniqueNumbers);
return numberList.get(numberList.size()-1);
}
}
package com.creativecode.hashtable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
import com.creativecode.hashtable.StaticClass.Variables;
@SuppressWarnings("unused")
int valueNumber= 0;
Hashtable <Integer,String> personas = new Hashtable<>();
Variables.uniqueNumbers = new HashSet<>();
} catch (Exception e) {
// TODO: handle exception
}
}
public static int GenerateUnique(){
int randomNumber = 0;
randomNumber = ThreadLocalRandom.current().nextInt(Variables.max);
Variables.uniqueNumbers.add(randomNumber);
return randomNumber;
}
public static int getLastNumber(){
List<Integer> numberList = new ArrayList<>(Variables.uniqueNumbers);
return numberList.get(numberList.size()-1);
}
}
Usando JOptionPane
showMessageDialog (Component
parentComponent, Object message)
Este método crea una ventana que muestra un mensaje entregado en el parámetro message. El
parámetro parentComponent es para indicar la ventana padre. En estos primeros tutoriales
usaremos null en este parámetro.
package com.creativecode.ui;
import javax.swing.JOptionPane;
package com.creativecode.ui;
import java.text.MessageFormat;
import javax.swing.JOptionPane;
showConfirmDialog
JOptionPane.showConfirmDialog(Componente padre, mensaje, titulo, tipo de
seleccion, tipo de mensaje, icono);
Componente sobre el que se abre el cuadro de diálogo (lo dejamos por defecto)
package com.creativecode.ui;
import java.text.MessageFormat;
import javax.swing.JOptionPane;
Combo JOptionPane
package com.creativecode.ui;
import java.text.MessageFormat;
import javax.swing.JOptionPane;
Clases y objetos
El proceso de creación de programas orientados a objetos implica, de manera resumida, la
creación de clases y la posterior creación de objetos basados en estas clases. Las clases sirven
como el modelo a partir del cual se estructuran los datos y comportamientos del programa.
Un ejemplo básico de un objeto, como mencionamos anteriormente, podría ser un animal. Para
representar este objeto, creamos un atributo llamado "edad" que almacena la edad del animal.
Además, el animal puede envejecer, por lo que podríamos definir un método que se encarga de
actualizar la edad. En resumen, una clase se encarga de definir tanto los datos (como el atributo
"edad") como la lógica (como el método de envejecimiento) relacionados con muchos objetos en
un programa. La clase proporciona una definición global y genérica que se utiliza para crear
múltiples instancias de objetos. La siguiente imagen nos ayuda a entender mejor la diferencia
entre clases y objetos.
Clases en Java
Para la creación de clases en Java se recomienda Crear paquetes que permitan organizar cada una
de las clases que se van a usar en el desarrollo software.
Declaración de la clase: Se utiliza la palabra clave class seguida del nombre de la clase, en
este caso, " MiClase ". Por convención, el nombre de la clase comienza con una letra
mayúscula.
Constructor: Es un método especial que se utiliza para crear e inicializar objetos de la clase.
En el ejemplo, se define un constructor público con el mismo nombre de la clase, " MiClase ",
y no realiza ninguna acción particular. Puede tener parámetros para recibir valores iniciales
de los atributos.
1.
2.
3.
4.
5.
Para el ejemplo practico se creara una clase llamada Equipo que contendrá la informacion de
todos los equipos de la liga de futbol colombiana. Siga los siguientes pasos:
1. Haga clic derecho sobre el paquete en el que se creara la clase. Para el caso practico se
creara en el paquete model.
2.
3.
4.
Modificadores de acceso
En Java, los modificadores de acceso se utilizan para establecer el nivel de acceso y visibilidad de
clases, métodos, constructores y atributos (variables de instancia) dentro de un programa. Los
modificadores de acceso controlan dónde se puede acceder y utilizar una clase, método o
variable.
1. public : El miembro (clase, método, variable) es accesible desde cualquier otra clase.
2. protected : El miembro es accesible dentro del mismo paquete y por las subclases en
cualquier paquete.
En Java, los métodos getter y setter son utilizados para acceder y modificar los valores de los
atributos privados de una clase. Estos métodos permiten el encapsulamiento de datos, una de las
características fundamentales de la programación orientada a objetos.
Paradigmas de la POO
Los principales paradigmas de la POO incluyen:
Encapsulamiento
El encapsulamiento es el concepto de ocultar los detalles internos de un objeto y exponer solo lo
necesario. Esto se logra mediante el uso de modificadores de acceso ( public , private ,
protected ) para controlar la visibilidad de los atributos y métodos de una clase. La idea es que
un objeto maneje su propio estado interno y que otros objetos interactúen con él solo a través de
métodos públicos.
Abstracción
La abstracción consiste en simplificar la complejidad mediante la modelación de clases que
representan conceptos abstractos del mundo real, capturando solo los detalles esenciales. Las
clases abstractas y las interfaces se utilizan para definir estructuras de datos y comportamientos
comunes.
Herencia
La herencia permite crear nuevas clases basadas en clases existentes. La nueva clase, llamada
subclase, hereda atributos y métodos de la clase base, permitiendo reutilizar y extender el código
existente.
public class Animal {
protected String nombre;
Super()
En Java, la palabra clave super se utiliza para referirse a la clase base inmediata de una clase
derivada. El uso de super() tiene dos propósitos principales:
Cuando una subclase se inicializa, es común que necesite inicializar algunos atributos definidos en
la clase base. Para ello, se usa super() para invocar el constructor de la clase base. Si no se
invoca explícitamente, Java automáticamente llama al constructor sin argumentos de la clase
base.
class Animal {
String nombre;
La palabra clave super también se puede utilizar para acceder a métodos y variables de la clase
base que han sido ocultados por la subclase.
class Animal {
public void hacerSonido() {
System.out.println("El animal hace un sonido");
}
}
Puntos Clave
Métodos y Variables: Se utiliza super para acceder a los métodos y variables de la clase
base cuando estos han sido sobreescritos en la subclase.
Los quipos de futbol pueden tener en su estructura interna jugadores, cuerpo técnico y masajistas
(Personal de recuperacion fisica).
Si observamos detenidamente todas las clases de la figura poseen atributos y métodos iguales.
Para dar solución a esta problemática acudimos al factor común el cual consiste en tomar los
atributos iguales y crear una clase principal que reuna estos atributos.
Polimorfismo
El polimorfismo permite a las clases derivadas ser tratadas como si fueran instancias de su clase
base. Hay dos tipos principales de polimorfismo: en tiempo de compilación (sobrecarga de
métodos) y en tiempo de ejecución (sobreescritura de métodos).
Test Conocimiento
¿Cuál de las siguientes opciones define correctamente la encapsulación en Java?
¿Qué modificador de acceso permite que un miembro de una clase sea accesible solo dentro del
mismo paquete y por las subclases en cualquier paquete?
A. public
B. private
C. protected
D. (default) [sin modificador]
class Animal {
public void hacerSonido() {
System.out.println("El animal hace un sonido");
}
}
Patrones de diseño
Un patrón de diseño es una solución reusable a problemas comunes en el diseño de software. Se
trata de descripciones o plantillas de cómo resolver un problema que se presenta repetidamente
en el desarrollo de software. Los patrones de diseño no son piezas de código concreto, sino más
bien formas generales de organizar el código y las interacciones entre objetos y clases.
Existen varios tipos de patrones de diseño, y se pueden clasificar en tres categorías principales:
1. Patrones Creacionales:
Factory Method: Define una interfaz para crear un objeto, pero permite a las subclases
alterar el tipo de objetos que se crearán.
Abstract Factory: Provee una interfaz para crear familias de objetos relacionados o
dependientes sin especificar sus clases concretas.
Singleton: Asegura que una clase tenga solo una instancia y proporciona un punto de
acceso global a ella.
Adapter: Permite que clases con interfaces incompatibles trabajen juntas mediante una
interfaz de adaptación.
Proxy: Proporciona un sustituto o marcador de posición para otro objeto para controlar
el acceso a él.
3. Patrones de Comportamiento:
Observer: Define una dependencia uno a muchos entre objetos para que cuando uno
cambie su estado, todos sus dependientes sean notificados y actualizados
automáticamente.
Strategy: Define una familia de algoritmos, encapsula cada uno, y los hace
intercambiables.
SOLID
SOLID se refiere a cinco principios de diseño de software orientado a objetos que buscan mejorar
la calidad, mantenibilidad y escalabilidad del código. Estos principios son los siguientes:
Ejemplo
Supongamos que estamos desarrollando una aplicación para la gestión de empleados. En un mal
diseño, podríamos tener una clase Employee que no solo gestione la información del empleado,
sino que también maneje la lógica de persistencia (guardar, actualizar y eliminar empleados en
una base de datos).
Mal diseño
// Getters y setters
// Getters y setters
}
// Clase EmployeeRepository que maneja la persistencia de los empleados
public class EmployeeRepository {
public void save(Employee employee) {
// Código para guardar el empleado en la base de datos
}
Uso clases
repository.save(employee);
// Otros métodos de repository como update() y delete()
}
}
Supongamos que estamos desarrollando un sistema de cálculo de salarios para diferentes tipos
de empleados (por ejemplo, empleados a tiempo completo y empleados contratados). Queremos
que el sistema sea extensible sin necesidad de modificar el código existente cuando se agregue
un nuevo tipo de empleado.
// Getters y setters
}
Este diseño viola el OCP porque cada vez que se añade un nuevo tipo de empleado, se
necesita modificar la clase SalaryCalculator .
@Override
public double calculateSalary() {
return getBaseSalary();
}
}
// Empleado contratado
public class ContractorEmployee extends Employee {
public ContractorEmployee(String id, String name, double baseSalary) {
super(id, name, baseSalary);
}
@Override
public double calculateSalary() {
return getBaseSalary() * 0.8;
}
}
// Implementación de SalaryCalculator
public class DefaultSalaryCalculator implements SalaryCalculator {
@Override
public double calculateSalary(Employee employee) {
return employee.calculateSalary();
}
}
public class Main {
public static void main(String[] args) {
Employee fullTimeEmployee = new FullTimeEmployee("1", "John Doe", 50000);
Employee contractorEmployee = new ContractorEmployee("2", "Jane Smith",
40000);
Supongamos que estamos desarrollando una aplicación para un zoológico y tenemos una clase
Bird y sus subclases. Queremos asegurarnos de que cualquier subclase de Bird pueda ser
usada donde sea que se use la clase Bird sin afectar la funcionalidad del programa.
En este diseño, la clase Penguin viola el LSP porque su implementación del método fly() no es
consistente con la clase base Bird . Esto puede llevar a comportamientos inesperados o errores
en tiempo de ejecución.
Para adherirse al LSP, podemos introducir una jerarquía de clases más adecuada que refleje
correctamente las capacidades de las diferentes aves.
@Override
public void move() {
fly();
}
@Override
public void move() {
walk();
}
Claridad: Las responsabilidades de cada clase están claramente definidas y reflejan las
capacidades reales de las aves.
@Override
public void eat() {
System.out.println("Eating lunch");
}
@Override
public void sleep() {
System.out.println("Sleeping at home");
}
}
@Override
public void eat() {
// Los robots no comen, esto no tiene sentido
throw new UnsupportedOperationException("Robots don't eat");
}
@Override
public void sleep() {
// Los robots no duermen, esto no tiene sentido
throw new UnsupportedOperationException("Robots don't sleep");
}
}
En este diseño, la interfaz Worker fuerza a que todas las implementaciones incluyan métodos que
no son aplicables a ciertos tipos de trabajadores, como los robots.
@Override
public void eat() {
System.out.println("Eating lunch");
}
@Override
public void sleep() {
System.out.println("Sleeping at home");
}
}
Flexibilidad: Las clases solo implementan las interfaces que realmente necesitan, evitando la
implementación de métodos no aplicables.
Reusabilidad: Los componentes se pueden reutilizar de manera más efectiva, ya que solo
dependen de las interfaces necesarias.
public UserService() {
this.database = new MySQLDatabase();
}
En este diseño, UserService depende directamente de MySQLDatabase , lo que hace que sea
difícil cambiar la implementación de la base de datos sin modificar UserService .
@Override
public void disconnect() {
System.out.println("Disconnecting from MySQL database...");
}
@Override
public void getData() {
System.out.println("Fetching data from MySQL database...");
}
}
@Override
public void disconnect() {
System.out.println("Disconnecting from Oracle database...");
}
@Override
public void getData() {
System.out.println("Fetching data from Oracle database...");
}
}
Resumiendo....
Principio de Responsabilidad Única (SRP): Cada clase debe tener una sola responsabilidad o
motivo para cambiar.
Principio de Abierto/Cerrado (OCP): Las clases deben estar abiertas para extensión, pero
cerradas para modificación. Es decir, deberías poder añadir nuevas funcionalidades sin cambiar el
código existente.
Principio de Sustitución de Liskov (LSP): Las subclases deben ser reemplazables por sus clases
base sin alterar el comportamiento del programa. Las subclases deben poder usarse en lugar de
las clases base sin problemas.
Principio de Segregación de Interfaces (ISP): Los clientes no deben verse obligados a depender
de interfaces que no usan. Es mejor tener interfaces específicas y pequeñas.
Principio de Inversión de Dependencias (DIP): Las clases de alto nivel no deben depender de
clases de bajo nivel. Ambas deben depender de abstracciones. Las abstracciones no deben
depender de detalles; los detalles deben depender de abstracciones.
Problema
crear un programa simple de una tienda en línea, donde aplicaremos todos los principios SOLID.
Imaginemos que tenemos un sistema donde los clientes pueden realizar pedidos y los pedidos se
pueden pagar utilizando diferentes métodos de pago.
// Clase Producto
class Product {
private String name;
private double price;
// Clase Pedido
class Order {
private List<Product> products;
public Order() {
products = new ArrayList<>();
}
// Clase Pago
class Payment {
public void pay(Order order) {
System.out.println("Paying " + order.calculateTotal());
}
}
Cada clase debe tener una sola responsabilidad. Vamos a separar las responsabilidades de cálculo
de total y de pago.
// Clase Pedido
class Order {
private List<Product> products;
public Order() {
products = new ArrayList<>();
}
Cada clase debe tener una sola responsabilidad. Vamos a separar las responsabilidades de cálculo
de total y de pago.
// Clase Pedido
class Order {
private List<Product> products;
public Order() {
products = new ArrayList<>();
}
Vamos a permitir la extensión del método de pago sin modificar la clase Payment .
// Interfaz PaymentMethod
interface PaymentMethod {
void pay(double amount);
}
// Implementación de PayPal
class PayPalPayment implements PaymentMethod {
@Override
public void pay(double amount) {
System.out.println("Paying with PayPal: " + amount);
}
}
Creamos interfaces pequeñas y específicas si fuese necesario, pero en este caso ya lo hemos
hecho con PaymentMethod .
Las clases de alto nivel ( OrderProcessor ) no deben depender de clases de bajo nivel
( CreditCardPayment ), sino de abstracciones ( PaymentMethod ).
2. Driver: Una interfaz que maneja las comunicaciones con el servidor de la base de datos.
Cada base de datos necesita su propio controlador.
3. Connection: Una interfaz que proporciona métodos para trabajar con la conexión a la base
de datos, como crear sentencias y administrar transacciones.
4. Statement: Una interfaz que representa una sentencia SQL que se puede ejecutar contra la
base de datos. Tiene subinterfaces como PreparedStatement (para sentencias SQL
precompiladas) y CallableStatement (para llamadas a procedimientos almacenados).
5. ResultSet: Una interfaz que representa el conjunto de resultados devueltos por una
sentencia SQL, permitiendo iterar sobre los datos obtenidos de una consulta.
6. SQLException: Una clase que maneja cualquier error que ocurra en el acceso a la base de
datos
jdbc:mysql:// : Este es el protocolo que indica que estás utilizando JDBC para conectarte a
una base de datos MySQL.
localhost : Este es el hostname o la dirección IP del servidor donde está alojada la base de
datos. En este caso, localhost se refiere a la máquina local donde se está ejecutando el
código.
3306 : Este es el número de puerto en el cual el servidor MySQL está escuchando las
conexiones. El puerto por defecto para MySQL es 3306 .
mydatabase : Este es el nombre de la base de datos a la que te estás conectando. Debe ser
reemplazado por el nombre real de tu base de datos.
user : Este es el nombre de usuario que se utiliza para autenticarse en la base de datos. En
este ejemplo, el usuario es root , que es el usuario administrador por defecto en MySQL. En
un entorno de producción, generalmente utilizarás un nombre de usuario con privilegios
más limitados.
Ejemplo completo
package com.videogames;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Videogames {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/juegos";
String user = "root";
String password = "123456";
try {
Connection connection = DriverManager.getConnection(url, user,
password);
System.out.println("Conexión exitosa!");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package com.videogames;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
// Crear tabla
String createTableSQL = "CREATE TABLE IF NOT EXISTS games (" +
"id INT PRIMARY KEY AUTO_INCREMENT, " +
"name VARCHAR(50))";
statement.execute(createTableSQL);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Insertar datos
package com.videogames;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
// Crear tabla
String insertDataSQL = "INSERT INTO games (name) VALUES " +
"('The Legend of Zelda: Breath of the Wild'), " +
"('Super Mario Odyssey')";
statement.executeUpdate(insertDataSQL);
System.out.println("Juegos registrados");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Consultar información
package com.videogames;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.MessageFormat;
// Consultar datos
String query = "SELECT id,name FROM games";
ResultSet resultSet = statement.executeQuery(query);
// Procesar resultados
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println(MessageFormat.format("Id juego {0} -
Nombre {1}",id,name));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Actualizar Informacion
package com.videogames;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
// Operación UPDATE
String updateSQL = "UPDATE juegos.games SET name = 'The Legend of
Zelda: Breath of the Wild - Updated' WHERE id = 1";
int rowsUpdated = statement.executeUpdate(updateSQL);
System.out.println("Número de filas actualizadas: " +
rowsUpdated);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Eliminar registros
package com.videogames;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
// Operación DELETE
String deleteSQL = "DELETE FROM games WHERE id = 1";
int rowsDeleted = statement.executeUpdate(deleteSQL);
System.out.println("Número de filas eliminadas: " + rowsDeleted);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
GamesCRUD/
│
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── controller/
│ │ │ │ └── GameController.java
│ │ │ │
│ │ │ ├── model/
│ │ │ │ ├── Game.java
│ │ │ │ └── GameDAO.java
│ │ │ │
│ │ │ └── view/
│ │ │ └── GameView.java
│ │ │
│ │ └── resources/
│ │ └── db.properties
│ │
│ └── test/
│ └── java/
│ └── controller/
│ └── GameControllerTest.java
│
├── .gitignore
├── pom.xml (o build.gradle)
└── README.md
Código proyecto
https://github.com/trainingLeader/videogames.git
Game.java
package com.videogames.model;
GameDao.java
package com.videogames.model;
/*
Las importaciones incluyen las clases necesarias para manejar conexiones de
base de datos (Connection, DriverManager), ejecutar consultas SQL
(PreparedStatement, Statement, ResultSet), manejar excepciones SQL
(SQLException), y manejar propiedades (Properties).
*/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/*
Clase GameDao: Define la clase que se encargará de las operaciones
sobre la base de datos.
Atributo connection: Este atributo almacenará la conexión activa a la
base de datos.
Propiedades de la Base de Datos:
public GameDao() {
try {
Properties props = new Properties();
props.load(getClass().getClassLoader().getResourceAsStream("db.properties"))
;
String url = props.getProperty("url");
String user = props.getProperty("user");
String password = props.getProperty("password");
connection = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
}
/*
Consulta SQL:
String query = "INSERT INTO games (name) VALUES (?)": Define una
consulta SQL parametrizada para insertar un nuevo
juego.
Preparar la Consulta:
PreparedStatement ps = connection.prepareStatement(query): Crea un
PreparedStatement a partir de la consulta SQL. El
uso de PreparedStatement evita inyecciones SQL y permite manejar
parámetros de manera segura.
Asignar Parámetros:
ps.setString(1, game.getName()): Establece el valor del primer
parámetro (nombre del juego).
Ejecutar la Consulta:
ps.executeUpdate(): Ejecuta la consulta de inserción en la base de
datos.
*/
public void addGame(Game game) throws SQLException {
String query = "INSERT INTO games (name) VALUES (?)";
PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1, game.getName());
ps.executeUpdate();
}
/*
Crear una Lista de Juegos:
String query = "SELECT * FROM games": Define una consulta SQL para
seleccionar todos los juegos.
Crear un Statement y Ejecutar la Consulta:
String query = "UPDATE games SET name = ? WHERE id = ?": Define una
consulta SQL parametrizada para actualizar un
juego.
Preparar la Consulta:
String query = "DELETE FROM games WHERE id = ?": Define una consulta
SQL parametrizada para eliminar un juego.
Preparar la Consulta:
GameController.java
package com.videogames.controller;
import java.sql.SQLException;
import java.util.List;
import com.videogames.model.Game;
import com.videogames.model.GameDao;
import com.videogames.view.GameView;
GameView.java
package com.videogames.view;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
import com.videogames.model.Game;
public GameView() {
scanner = new Scanner(System.in);
}
public int showMenu() {
//clearConsole();
System.out.println("1. Añadir juego");
System.out.println("2. Listar juegos");
System.out.println("3. Actualizar juego");
System.out.println("4. Eliminar juego");
System.out.println("5. Salir");
System.out.print("Selecciona una opción: ");
return scanner.nextInt();
}
public Game getGameDetails() {
scanner.nextLine();
System.out.println("Nombre del juego: ");
String name = scanner.nextLine();
return new Game(0, name);
}
public int getGameId() {
System.out.print("ID del juego: ");
return scanner.nextInt();
}
public void showGames(List<Game> games) {
@SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
int pageSize = 3;
int totalGames = games.size();
int totalPages = (int) Math.ceil((double) totalGames / pageSize);
String leftAlignFormat = "| %-4d | %-40s |%n";
System.out.format("+------+--------------------------------------
----+%n");
System.out.println("Página " + page + " de " + totalPages);
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
scanner.nextLine();
clearConsole();
}
}
}
public void showMessage(String message) {
System.out.println(message);
}
public static void clearConsole() {
try {
if (System.getProperty("os.name").contains("Windows")) {
new ProcessBuilder("cmd", "/c",
"cls").inheritIO().start().waitFor();
} else {
new ProcessBuilder("clear").inheritIO().start().waitFor();
}
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
}
}
db.properties
url=jdbc:mysql://localhost:3306/juegos
user=root
password=123456
Arquitectura de software
Definiciones
“La Arquitectura de Software se refiere a las estructuras de un sistema, compuestas de
elementos con propiedades visibles de forma externa y las relaciones que existen entre ellos.
“
— Software Engineering Institute (SEI)
“El conjunto de estructuras necesarias para razonar sobre el sistema, que comprende
elementos de software, relaciones entre ellos, y las propiedades de ambos. “
— Documenting Software Architectures: Views and Beyond (2nd
Edition), Clements et al, AddisonWesley, 2010
my-hexagonal-console-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── adapter/
│ │ │ │ ├── in/
│ │ │ │ │ └── console/
│ │ │ │ │ └── ConsoleAdapter.java
│ │ │ │ └── out/
│ │ │ │ └── persistence/
│ │ │ │ └── MySQLUserRepository.java
│ │ │ ├── application/
│ │ │ │ └── usecase/
│ │ │ │ └── CreateUserUseCase.java
│ │ │ ├── domain/
│ │ │ │ └── User.java
│ │ │ ├── infrastructure/
│ │ │ │ ├── config/
│ │ │ │ │ └── DatabaseConfig.java
│ │ │ │ └── persistence/
│ │ │ │ └── UserRepository.java
│ │ │ └── main/
│ │ │ └── Main.java
│ └── test/
└── pom.xml
Dominio
User.java
package domain;
User service
package domain;
Aplicación
CreateUserUseCase.java
package application.usecase;
import domain.User;
import domain.UserService;
Infraestructura
DatabaseConfig.java
package infrastructure.config;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
Adaptadores
ConsoleAdapter.java
package adapter.in.console;
import application.usecase.CreateUserUseCase;
import domain.User;
import java.util.Scanner;
createUserUseCase.execute(user);
MySQLUserRepository.java
package adapter.out.persistence;
import domain.User;
import domain.UserService;
import infrastructure.config.DatabaseConfig;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@Override
public void createUser(User user) {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
statement.setString(1, user.getName());
statement.setString(2, user.getEmail());
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public User findUserById(Long id) {
String sql = "SELECT id, name, email FROM users WHERE id = ?";
User user = null;
statement.setLong(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
user = new User();
user.setId(resultSet.getLong("id"));
user.setName(resultSet.getString("name"));
user.setEmail(resultSet.getString("email"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
}
Main
package main;
import adapter.in.console.ConsoleAdapter;
import adapter.out.persistence.MySQLUserRepository;
import application.usecase.CreateUserUseCase;
import domain.UserService;
consoleAdapter.start();
}
}
Expresiones Lambda
Las expresiones lambda en Java, introducidas en la versión 8 del lenguaje, son una característica
que permite tratar las funciones como objetos. Proveen una sintaxis más concisa y flexible para la
implementación de interfaces funcionales, que son interfaces con un único método abstracto.
Con un Parámetro:
(x) -> x * x
(a, b) -> a + b
Bloque de Código:
package com.breaklinestudio.projectintro;
import java.util.Arrays;
import java.util.List;
2. Clase Principal: La clase Main contiene el método main , que es el punto de entrada del
programa.
3. Crear una Lista: En el método main , se crea una lista de cadenas lista que contiene los
elementos "uno", "dos" y "tres".
4. Iteración con Lambda: Utilizando el método forEach y una expresión lambda, el programa
itera sobre cada elemento de la lista e imprime cada elemento en la consola.
Comparator es una interfaz funcional que tiene un único método abstracto llamado
compare .
Su firma es int compare(T o1, T o2) , donde T es el tipo de los objetos a comparar (en
este caso, Persona ).
@Override
public String toString() {
return nombre + " - " + edad;
}
}
package com.breaklinestudio.projectintro;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
Collections.sort(personas, porEdad);
Parámetros de la Lambda:
(p1, p2) son los dos parámetros de la expresión lambda. Representan los dos objetos
Persona que queremos comparar.
Cuerpo de la Lambda:
Integer.compare(int x, int y)
Integer
que compara dos valores
int
y devuelve:
Cero si x es igual a y .
Consumer
En Java, Consumer es una interfaz funcional introducida en Java 8 como parte del paquete
java.util.function . La interfaz Consumer representa una operación que toma un solo
argumento y no devuelve ningún resultado. Se utiliza principalmente para pasar operaciones que
se aplicarán a cada elemento de una colección de elementos, como con el método forEach de las
colecciones.
Características de Consumer
Interfaz Funcional: Consumer es una interfaz funcional, lo que significa que tiene un solo
método abstracto.
package com.breaklinestudio.projectintro;
@Override
public String toString() {
return nombre + " - " + nota;
}
}
package com.breaklinestudio.projectintro;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
// Usar una expresión lambda con Consumer para imprimir el nombre de cada
estudiante
Consumer<Estudiante> imprimirNombre = estudiante ->
System.out.println(estudiante.getNombre());
BiConsumer
BiConsumer es una interfaz funcional en Java que se introdujo en Java 8 como parte del paquete
java.util.function . Al igual que Consumer , BiConsumer representa una operación que acepta
dos argumentos y no devuelve ningún resultado. Se utiliza principalmente cuando se desea
realizar una operación en un par de objetos.
Características de BiConsumer
Interfaz Funcional: BiConsumer es una interfaz funcional, lo que significa que tiene un
único método abstracto.
A continuación, un ejemplo de cómo usar BiConsumer para procesar un Map de claves y valores.
package com.breaklinestudio.projectintro;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
Supplier
En Java, Supplier es una interfaz funcional que se introdujo en Java 8 como parte del paquete
java.util.function . Supplier representa una función que no toma argumentos y proporciona
un resultado. Se usa principalmente en situaciones donde necesitas generar o proporcionar
valores sin necesidad de parámetros de entrada.
Características de Supplier
Interfaz Funcional: Supplier es una interfaz funcional, lo que significa que tiene un único
método abstracto.
Sintaxis de Supplier
La sintaxis básica de una expresión lambda que implementa un Supplier es:
() -> expresión
package com.breaklinestudio.projectintro;
import java.util.Random;
import java.util.function.Supplier;
package com.breaklinestudio.projectintro;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.function.Supplier;
Usamos el método get() del Supplier para obtener varias instancias de Persona y
las imprimimos.
Predícate
En Java, Predicate es una interfaz funcional que se introdujo en Java 8 como parte del paquete
java.util.function . Un Predicate representa una función que toma un solo argumento y
devuelve un valor booleano. Se usa comúnmente para pruebas o evaluaciones de condiciones
sobre datos.
Características de Predicate
Interfaz Funcional: Predicate es una interfaz funcional, lo que significa que tiene un único
método abstracto.
and: Combina este predicado con otro predicado usando una operación lógica AND.
or: Combina este predicado con otro predicado usando una operación lógica OR.
package com.breaklinestudio.projectintro;
import java.util.function.Predicate;
package com.breaklinestudio.projectintro;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
numeros.stream().filter(esPar).collect(Collectors.toList());
3. Combinación de Predicados
package com.breaklinestudio.projectintro;
import java.util.function.Predicate;
}
}
package com.breaklinestudio.projectintro;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
.collect(Collectors.toList());
Stream
En Java, un Stream es una secuencia de elementos que permite realizar operaciones sobre los
datos de manera declarativa y funcional. Los Streams se introdujeron en Java 8 como parte del
paquete java.util.stream y son una herramienta poderosa para procesar colecciones de datos.
4. Inmutables: Los Streams no modifican la colección original sino que producen un nuevo
Stream con los resultados.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
.collect(Collectors.toList());
}
}
3. collect
Recoge los elementos de un Stream en una colección.
4. forEach
Aplica una acción a cada elemento del Stream.
5. reduce
Reduce los elementos del Stream a un único valor.
package com.breaklinestudio.projectintro;
import java.util.stream.Stream;
package com.breaklinestudio.projectintro;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
Generar Ejecutable
Instalar en linux
Siga la siguiente guia https://www.digitalocean.com/community/tutorials/install-maven-linux-ubun
tu
Copiar la carpeta en la unidad de disco C;/ o donde desee copiar la descarga. Para la guia se
copiara en c:
Crear las Variables de entorno. Para configurar las variable de entorno en el buscador de
aplicaciones escriba Variables de
entorno.
Seleccione la ruta donde copio la carpeta de maven. Para el caso de la guia C:\apache-maven.
En la ventana de variables de entorno haga clic en el boton
En la ventana de creacion de la variable de entorno ingrese los datos segun los datos
obtenidos en los pasos anteriores. Ver imagen.
En la seccion variables del sistema seleccione path y presione el boton editar.
En la ventana de edicion de las variables de path seleccione nuevo y escriba
%MAVEN_HOME%\bin y haga clic en el boton de aceptar para terminar.
Por ultimo para cerrar la ventana de configuración de variables de entorno haga clic en el
boton aceptar.
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.NombreProyecto.NombreClasePrincipal</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<groupId>com.ligabetplay</groupId>
<artifactId>ligabetplay</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.ligabetplay.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Abra la terminal de visual studio code o power shell. Debe estar ubicado en la carpeta del
proyecto, ingrese el siguiente comando :