Skip to content

Commit 7d143b7

Browse files
committed
Explicaciones de optionals
1 parent 4190575 commit 7d143b7

1 file changed

Lines changed: 204 additions & 0 deletions

File tree

  • modules/src/main/java/com/platzi/functional/_14_optionals
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
package com.platzi.functional._14_optionals;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
import java.util.Optional;
6+
7+
public class Optionals {
8+
/*
9+
* La clase Optional nos ayuda en java 8 a resolver un problema comun en Java: null
10+
* Con Optional tendremos la posibilidad de operar sobre una clase que nos protege del infame NPE
11+
*
12+
* La idea de Optional es que previo a hacer una operacion, se haga una validacion dentro de
13+
* el Optional para evitar problemas.
14+
*/
15+
static Optional<String> ejemplos() {
16+
//La clase optional nos ofrece diferentes maneras de crear un optional segun los datos que tengamos
17+
18+
//El primero de ellos es crear un Optional de un dato que SI tenemos:
19+
Optional<String> optional = Optional.of("Java 8");
20+
21+
//Si no estamos seguros del valor que pondremos en el Optional, podemos usar ofNullable:
22+
optional = Optional.ofNullable(uknownResult());
23+
24+
//Y si lo que queremos es evitar devolver un null pero no tenemos un valor para regresar,
25+
//podemos usar simplemente:
26+
return Optional.empty();
27+
}
28+
29+
30+
//
31+
//
32+
//
33+
//
34+
35+
static void obtenerUnDato() {
36+
Optional<String> optional = Optional.ofNullable(uknownResult());
37+
38+
//Una vez que tenemos un optional, obtener el dato puede ser tan simple como:
39+
String dato = optional.get();
40+
41+
42+
//Sin embargo, eso nos provoca el mismo problema que tratamos de solucionar,
43+
//pues si el dato es null, `get` nos devolera un null.
44+
45+
46+
47+
//Podemos entonces, checar la presencia de dato:
48+
if (optional.isPresent()) {
49+
//Pero esto es muy similar a checar si el dato es null.
50+
dato = optional.get();
51+
}
52+
53+
54+
55+
//Hagamoslo de manera mas funcional:
56+
dato = optional.orElse("");
57+
58+
59+
//Y en caso de que nuestro dato sea muy complejo:
60+
dato = optional.orElseGet(Optionals::complexFunction);
61+
62+
63+
//O con una lambda:
64+
dato = optional.orElseGet(() -> /*Cosas magicas para generar el dato*/ "");
65+
66+
67+
68+
//Y esta es la parte donde entendemos que optional tiene mas poderes que validar contra un null.
69+
70+
71+
72+
//No solo eso, Optional nos permite operar el dato en caso de que este presente:
73+
optional.ifPresent(System.out::println);
74+
optional.ifPresent(s -> someComplexOperation(s));
75+
76+
77+
78+
//Incluso hacer operaciones para generar nuevos optionals segun sea necesario:
79+
Optional<String> subOptional = optional.filter(String::isEmpty);
80+
81+
82+
83+
//O transformar el dato:
84+
Optional<Integer> integerOptional = optional.map(s -> s.length() * 2);
85+
86+
87+
88+
//Es importante mencionar que Optional no ejecutara ninguna de estas funciones
89+
//en casos donde el dato no existe (null, empty() ). Asi que es seguro.
90+
91+
//Optional nos da un acercamiento hacia un concepto que en FP se conoce como Monad
92+
}
93+
94+
95+
/**
96+
* Ejemplo al codigo antes de Optional
97+
*/
98+
static String antesDeOptional(List<String> names) {
99+
//Antes de optional, era comun tener un pequeño `if` validando la presencia de valor
100+
// en los argumentos de nuestros metodos
101+
if (names == null) {
102+
103+
//Y una mala practica era, en error o ausencia de datos, retornar un null.
104+
//Esto es una mala practica porque es una manera de evadir operaciones. Forzando que tambien
105+
//el codigo que invoco nuestra funcion tenga que validar si el resultado es null.
106+
return null;
107+
}
108+
109+
return Arrays.toString(names.toArray());
110+
}
111+
112+
//
113+
//
114+
//
115+
//
116+
//
117+
//
118+
//
119+
//
120+
//
121+
//
122+
123+
//
124+
//
125+
//
126+
//
127+
//
128+
//
129+
130+
/**
131+
* Con la clase optional le damos una mayor seguridad a quien ejecuta nuestro codigo,
132+
* pues le ahorramos operaciones de validacion y puede decidir que hacer con los datos
133+
* de una manera mas directa.
134+
*/
135+
static Optional<String> conOptional(List<String> names) {
136+
if (names == null || names.isEmpty()) {
137+
return Optional.empty();
138+
}
139+
140+
return Optional.of(Arrays.toString(names.toArray()));
141+
}
142+
143+
144+
//
145+
//
146+
//
147+
//
148+
//
149+
//
150+
//
151+
//
152+
//
153+
//
154+
//
155+
//
156+
157+
/**
158+
* Funcion usando ambos casos:
159+
*/
160+
static void outside() {
161+
//Invocando a un metodo que no sabemos que devuelve:
162+
String directResult = antesDeOptional(null);
163+
if (directResult != null) {
164+
directResult = directResult.replace("Sierisimo", "Sinuhe");
165+
}
166+
167+
//Con optional:
168+
Optional<String> optionalResult = conOptional(null);
169+
170+
directResult = optionalResult
171+
.map(s -> s.replace("Sierisimo", "Sinuhe"))
172+
.orElse("Sinuhe");
173+
174+
//Incluso podriamos hacer chaining directo:
175+
conOptional(null).filter(s -> !s.isEmpty())
176+
.map(s -> s.replace("@Sierisimo", "Sinuhe"))
177+
.orElse("Sinuhe");
178+
179+
//Como vemos, optional nos facilita operar sobre datos
180+
}
181+
182+
//
183+
//
184+
//
185+
//
186+
//
187+
//
188+
//
189+
//
190+
//
191+
//
192+
//
193+
static String uknownResult() {
194+
return null;
195+
}
196+
197+
static String complexFunction() {
198+
return "Complex Result";
199+
}
200+
201+
static void someComplexOperation(String s) {
202+
203+
}
204+
}

0 commit comments

Comments
 (0)