La primera vez que estuve expuesto a expresiones Lambda fue en TypeScript (el superset de JavaScript), y fue para hacer el método de mecanografiado fuera de este método en lugar de en este método. Después de usarlo, de repente me di cuenta de que Lambda no es una nueva característica de peso pesado de JDK8. Así que sentí que revisé la información relevante y la grabé:
1. Parametrización del comportamiento
En resumen, la parametrización de comportamiento significa que el cuerpo de la función solo contiene un código general similar a la plantilla, mientras que alguna lógica que cambia con el escenario comercial se transmite a la función en forma de parámetros. El uso de la parametrización del comportamiento puede hacer que el programa sea más general para hacer frente a las necesidades de los cambios frecuentes.
Considere un escenario comercial, suponiendo que necesitamos filtrar a Apple a través de un programa, primero definimos una entidad de Apple:
public class Apple {/** Number*/private long id;/** color*/private color color;/** weight*/private float weight;/** origen*/private string origin; public Apple () {} public Apple (Long Id, Color Color, Float Weight, String Origin) {this.id = id; this.color = color; this.La demanda inicial de los usuarios puede ser simplemente filtrar manzanas verdes a través del programa, por lo que podemos implementarlas rápidamente a través del programa:
Lista estática pública <Apple> FilterGreenApples (List <Apple> Apple) {List <Apple> FilterApples = New ArrayList <> (); para (Apple Final Apple: Apple) {if (color.green.equals (Apple.getColor ())) {FilterApples.Add (Apple);} Return Filterapples;}Este código es simple y no vale la pena decirlo. Pero cuando el usuario necesita ser verde, parece que modificar el código es simple, no es más que cambiar el verde de la condición del juicio a rojo. Pero debemos considerar otro problema. Si las condiciones cambiantes cambian con frecuencia, ¿esto se hace? Si es solo un cambio de color, entonces podemos dejar que el usuario pase en las condiciones de juicio del color, y los parámetros del método de juicio cambian "el conjunto a juzgar y el color a filtrar". Pero, ¿qué pasa si el usuario no solo juzga el color, sino que también quiere juzgar el peso, el tamaño, etc.? ¿Crees que podemos agregar diferentes parámetros para completar el juicio? Pero, ¿es realmente bueno pasar parámetros como este? Si hay más y más condiciones de filtrado y el modo de combinación se vuelve cada vez más complejo, ¿debemos considerar todas las situaciones y tener estrategias de afrontamiento correspondientes para cada situación? En este momento, podemos parametrizar el comportamiento, extraer las condiciones de filtrado y pasarlas como parámetros. En este momento, podemos encapsular una interfaz de juicio:
Interfaz pública AppleFilter {/*** Filtro Resumen ** @param Apple* @return*/boolean Acept (Apple Apple);}/*** Los filtros de encapsulación en la interfaz ** @param manzanas*@param filter* @return*/public static list <Apple> filterapplesbyaplefilter (list <Apple> Appleples, Applefilter Filter) {Lista <Apple> Filterapples = NewaplapapsyList (New ArtleArtArmleAn. para (Apple Final Apple: Apple) {if (Filter.accept (Apple)) {FilterApples.Add (Apple);}} return FilterApples;}Después de la abstracción de comportamiento anterior, podemos establecer las condiciones del filtro en la llamada específica y pasar las condiciones como parámetros al método. En este momento, utilizamos el método de la clase interna anónima:
public static void main (string [] args) {list <saple> manzanas = new ArrayList <> (); // Filter Apple List <Pe Apple> FilterApples = FilterApplesByAppleFilter (Apples, New AppleFilter () {@OverridePublic Boolean Acept (Apple Apple) {// Filtro Red Apples con peso más que 100G de regreso. Apple.getWeight ()> 100;}});}Este diseño se usa a menudo dentro de JDK, como java.util.comparator, java.util.concurrent.callable, etc., etc., cuando utilizan este tipo de interfaz, podemos usar clases anónimas para especificar la lógica de ejecución específica de la función en los lugares específicos de llamadas. Sin embargo, desde el bloque de código anterior, aunque es muy geek, no es lo suficientemente conciso. En Java8, podemos simplificarlo a través de Lambda:
// Filtro Apple List <Apple> FilterApples = FilterApplesByappleFilter (Apple, (Apple Apple) -> Color.Red.Equals (Apple.getColor ()) && Apple.getweight ()> = 100); // () -> xxx () es el método parámetros, y XXX es la implementación del método
2. Definición de expresión de Lambda
Podemos definir una expresión de lambda como una función anónima concisa y pasable. En primer lugar, debemos dejar en claro que la expresión de Lambda es esencialmente una función. Aunque no pertenece a una clase específica, tiene una lista de parámetros, cuerpo de función, tipo de retorno y la capacidad de arrojar excepciones; En segundo lugar, es anónimo, y la expresión de Lambda no tiene un nombre de función específico; La expresión de Lambda se puede pasar como parámetros, simplificando enormemente la escritura de código. La definición de formato es la siguiente:
Formato 1: Lista de parámetros -> Expresión
Formato 2: Lista de parámetros -> {Colección de expresiones}
Cabe señalar que la expresión de Lambda implica la palabra clave de retorno, por lo que en una sola expresión, no necesitamos escribir explícitamente la palabra clave de retorno, pero cuando la expresión es una colección de declaraciones, necesitamos agregar explícitamente retorno y encerrar múltiples expresiones con aparatos {}. Veamos algunos ejemplos a continuación:
// Devuelve la longitud de la cadena dada, Return Declary (String S) -> S.Length () // Siempre devuelve el método noarGumented () () - -> 42 // contiene múltiples líneas de expresión, encerradas en aparatos ondulados (int x, int y) -> {int z = x * y; return x + z;}3. Use expresiones lambda basadas en interfaces funcionales
El uso de expresiones lambda requiere la ayuda de interfaces funcionales, lo que significa que solo cuando aparece la interfaz funcional podemos simplificarlas con expresiones lambda.
Interfaz funcional personalizada:
Las interfaces funcionales se definen como interfaces que tienen solo un método abstracto. La mejora en la definición de interfaz de Java8 es introducir métodos predeterminados, para que podamos proporcionar implementaciones predeterminadas de métodos en la interfaz. Sin embargo, no importa cuántos métodos predeterminados existan, siempre que uno tenga y solo un método abstracto, es una interfaz funcional, como sigue (consulte el AppleFilter anterior):
/*** Interfaz de filtro Apple*/ @funcionalInterfacePublic Interface Applefilter {/*** Condición de filtro Resumen ** @param Apple* @return*/boolean Acept (Apple Apple);}AppleFilter solo contiene un método abstracto Aceptar (Apple Apple). Según la definición, se puede considerar como una interfaz funcional. Al definir, agregamos la anotación @FunctionalInterface a la interfaz para marcar la interfaz como una interfaz funcional. Sin embargo, esta interfaz es opcional. Después de agregar esta interfaz, el compilador restringe la interfaz para tener solo un método abstracto, de lo contrario se informará un error, por lo que se recomienda agregar esta anotación a la interfaz funcional.
JDK viene con interfaz funcional:
JDK es una expresión de Lambda con ricas interfaces funcionales. A continuación se presentan ejemplos de uso de predicado <t>, consumidor <t>, función <t, r> respectivamente.
Predicado:
@FunctionalInterfacePublic Interface Predicate <T> {/*** Evalúa esta predicción en el argumento dado. ** @param t El argumento de entrada* @return {@code true} Si el argumento de entrada coincide con el predicto,* de lo contrario {@code false}*/boolean test (t t);}La función del predicado es similar al AppleFilter anterior. Utiliza las condiciones que establecemos externamente para verificar los parámetros entrantes y devuelve el resultado de verificación booleano. Los siguientes usan predicados para filtrar los elementos de la colección de la lista:
/**** @param list* @param predicate* @param <t>* @return*/public <t> list <t> filter (list <t> list, predicate <t> predicate) {list <t> newList = new ArrayList <T> (); for (final t: list) {if (predicate.test (t)) {newList.add (t);}}usar:
demo.filter (list, (string str) -> null! = str &&! str.isempty ());
Consumidor
@FunctionalInterfacePublic Interface Consumer <T> {/*** Realiza esta operación en el argumento dado. ** @param t El argumento de entrada*/void acepta (t t);}El consumidor proporciona una función abstracta aceptada que recibe parámetros pero no devuelve valores. El siguiente utiliza el consumidor para atravesar la colección.
/*** Traversal de la colección y realiza el comportamiento personalizado ** @param list* @param consumidor* @param <t>*/public <t> void filtre (list <t> list, consumidor <t> consumidor) {for (final t t: list) {consumidor.accept (t);}}}Usando la interfaz funcional anterior, iterar a través de la colección de cadenas e imprimir cadenas no vacías:
demo.filter (list, (string str) -> {if (stringUtils.isnotblank (str)) {system.out.println (str);}});Función
@FunctionalInterfacePublic Interface Función <t, r> {/*** Aplica esta función al argumento dado. ** @param t El argumento de la función*@return el resultado de la función*/r aplica (t t);}La función realiza una operación de conversión. La entrada son datos del tipo T y devuelve datos del tipo R. La siguiente función usa para convertir el conjunto:
public <t, r> list <r> filter (list <t> list, function <t, r> function) {list <r> newList = new ArrayList <r> (); para (final t t: list) {newList.Add (function.apply (t));} return newList;}otro:
demo.filter (list, (string str) -> integer.parseInt (str));
Las interfaces funcionales anteriores también proporcionan algunas implementaciones predeterminadas de operaciones lógicas. Hablemos de ello más tarde al introducir los métodos predeterminados de la interfaz Java8 ~
Algunas cosas a las que prestar atención durante el uso:
Inferencia de tipo:
Durante el proceso de codificación, a veces podemos preguntarnos qué interfaz funcional coincidirá con nuestro código de llamada. De hecho, el compilador hará juicios correctos basados en parámetros, tipo de retorno, tipo de excepción (si está presente), etc.
Al llamar de maneras específicas, el tipo de parámetro se puede omitir en algunos momentos, simplificando así más el código:
// Filtro Apple List <Apple> FilterApples = FilterApplesByAppleFilter (Apple, (Apple Apple) -> color.Red.equals (Apple.getColor ()) && Apple.getweight ()> = 100); // En algunos casos, podemos omitir los tipos de parámetros y el compilador correctamente juzgar <Apple> FilterApples = FilterAppleByapplefilter (Apple, Apple, Apple -Anly -Apple -Le -Judge Correctamente juzgar. Color.red.equals (Apple.getColor ()) && Apple.getWeight ()> = 100);
Variables locales
Todos los ejemplos por encima de nuestras expresiones Lambda usan los parámetros de su cuerpo, también podemos usar variables locales en Lambda, de la siguiente manera
int weight = 100; list <saple> filterapples = filterapplesbyappleFilter (Apple, Apple -> color.red.equals (Apple.getColor ()) && Apple.getweight ()> = Weight);:::::
En este ejemplo, usamos el peso variable local en la lambda. Sin embargo, el uso de variables locales en la Lambda debe exigir que la variable se declare explícitamente como final o de hecho final. Esto se debe principalmente a que la variable local se almacena en la pila, y la expresión de lambda se ejecuta en otro hilo. Cuando la vista de hilo accede a la variable local, la variable tiene la posibilidad de ser cambiado o reciclado, por lo que no habrá problemas de seguridad de subprocesos después de la modificación con final.
IV. Cita de método
El uso de referencias de método puede hacer que el código sea más simplificado. A veces esta simplificación hace que el código se vea más intuitivo. Echemos un vistazo a un ejemplo:
/* ... omitir la operación de inicialización de manzanas* /// Use la expresión lambda Apples.sort ((Apple A, Apple B) -> Float.Compare (A.GetWeight (), B.GetWeight ())); // Use el método para referirse a Apple.sort (comparador.comparing (Apple :: Getweight));
Método Referencias Conectar Método de membresía y método a través de ::, que se dividen principalmente en tres categorías:
Método estático
(args) -> classname.staticMethod (args)
Convertirse en
Classname :: staticmethod
Método de ejemplo de parámetro
(args) -> args.instancemethod ()
Convertirse en
Classname :: instancemethod // classname es type args
Método de instancia externa
(args) -> ext.instancemethod (args)
Convertirse en
Ext :: Instancemethod (args)
referirse a:
http://www.codeceo.com/article/lambda-of-java-8.html
Lo anterior es la expresión lambda de la nueva función JDK8 que el editor le presentó. Espero que te sea útil. Si tiene alguna pregunta, déjame un mensaje y el editor le responderá a tiempo. ¡Muchas gracias por su apoyo al sitio web de Wulin.com!