Seleccione un solo elemento
Intuitivamente, seleccionar un solo elemento es definitivamente más fácil que seleccionar varios elementos, pero aquí existen algunos problemas. Primero veamos cuál es el problema con el enfoque general y luego veamos cómo usar expresiones lambda para resolverlo.
Primero creemos un nuevo método para encontrar un elemento que comience con una letra específica y luego imprimamos.
Copie el código de código de la siguiente manera:
nombre de selección de vacío estático público (
Lista final<Cadena> nombres, cadena final letra inicial) {
Cadena nombre encontrado = nulo;
para (nombre de cadena: nombres) {
if(nombre.startsWith(letra inicial)) {
nombre encontrado = nombre;
romper;
}
}
Este método apesta tanto como el camión de la basura que acaba de pasar. Primero creamos una nueva variable foundName y luego la inicializamos a nula; esta es la fuente del hedor. Tenemos que verificar si es nulo; de lo contrario, se generará una NullPointerException o una respuesta de error. También usamos un iterador externo para recorrer la lista. Si encontramos el elemento que queremos, tenemos que salir del bucle, lo que se suma al olor original: paranoia de tipo básico, estilo imperativo, mutabilidad, todo cobra vida. Una vez que salimos del bucle, tenemos que comprobar los resultados antes de imprimir. Una tarea tan pequeña en realidad requiere un código tan largo.
Volvamos a analizar este tema. Solo queremos poder seleccionar el primer elemento coincidente y manejar de forma segura el caso en el que no exista dicho elemento. Reescribamos este método pickName usando una expresión lambda.
Copie el código de código de la siguiente manera:
nombre de selección de vacío estático público (
Lista final<Cadena> nombres, cadena final letra inicial) {
final Opcional<Cadena> nombre encontrado =
nombres.stream()
.filtro(nombre ->nombre.startsWith(letra inicial))
.findFirst();
System.out.println(String.format("Un nombre que comienza con %s: %s",
letra inicial, nombre encontrado.oElse("No se encontró ningún nombre")));
}
Algunas funciones potentes del JDK hacen que este código sea muy conciso. Primero, usamos el método de filtro para obtener todos los elementos que cumplen las condiciones y luego usamos el método findFirst de la clase Stream para seleccionar el primer elemento de la colección devuelta. Este método devuelve un objeto Opcional, que es el desodorante certificado oficialmente para variables nulas en Java.
La clase Opcional es muy útil, no tienes que preocuparte por si el resultado existe o no. Nos salva del problema de las excepciones de puntero nulo y deja más claro que ningún resultado es un resultado posible. Mediante el método isPresent(), podemos saber si el resultado existe. Si queremos obtener el valor del resultado, podemos usar el método get(). También podemos establecer un valor predeterminado usando (el nombre de este método te sorprenderá) el método orElse, como en el código anterior.
Usamos la colección de amigos que hemos estado usando antes para verificar nuestro método pickName.
Copie el código de código de la siguiente manera:
elegirNombre(amigos, "N");
elegirNombre(amigos, "Z");
Este código selecciona el primer elemento coincidente e imprime un mensaje amigable si no se encuentra.
Copie el código de código de la siguiente manera:
Un nombre que comienza con N: Nate
Un nombre que comienza con Z: No se encontró ningún nombre
La combinación del método findFirst() y la clase Optinal reduce la cantidad de nuestro código y se ve bien. Pero las funciones de la clase Opcional son mucho más que eso. Por ejemplo, además de proporcionar un valor predeterminado cuando el objeto no existe, también puede usarlo para ejecutar un fragmento de código o una expresión lambda, si el resultado existe, como este:
Copie el código de código de la siguiente manera:
foundName.ifPresent(nombre -> System.out.println("Hola " + nombre));
En comparación con el código imperativo de seleccionar el primer nombre coincidente, el elegante estilo funcional del flujo se ve mejor. Pero, ¿hay mucho que hacer en esta versión del flujo de llamadas? Por supuesto que no, estos métodos son muy inteligentes y funcionan bajo demanda (exploraremos esto en profundidad en Evaluación diferida de transmisiones en la página 113).
El ejemplo de selección de un solo elemento muestra funciones más potentes de la biblioteca JDK. Veamos cómo las expresiones lambda pueden encontrar un valor deseado en función de una colección.