As expressões Java Lambda são um novo recurso introduzido pelo Java 8. Pode -se dizer que é considerado um açúcar de sintaxe para programação funcional simulada. Eles são semelhantes aos fechamentos em JavaScript, mas são um pouco diferentes. O principal objetivo é fornecer uma sintaxe funcional para simplificar nossa codificação.
Lambda Sintaxe básica
A estrutura básica do lambda é (argumentos) -> corpo, e existem várias situações:
O corpo precisa incluir declarações com {} e {} podem ser omitidas quando houver apenas uma declaração.
Os métodos de escrita comuns são os seguintes:
(a) -> a * a
(int a, int b) -> a + b
(a, b) -> {return a - b;}
() -> System.out.println (Thread.currentThread (). GetId ())
FuncionalInterface
conceito
As expressões Java Lambda são baseadas em interfaces funcionais. O que é uma interface funcional? Simplificando, é uma interface com apenas um método (função). O objetivo desse tipo de interface é para uma única operação, que é equivalente a uma única função. Interfaces comuns, como executável e comparador, são interfaces funcionais e são anotadas com @functionalInterface.
Dê um exemplo
É fácil de entender o uso de threads como exemplo. A interface executável é uma interface comumente usada quando encadeamos programação, que inclui um método void run (), que é a lógica em execução do Thread. De acordo com a sintaxe anterior, geralmente usamos a classe anônima executável para criar novos threads, como segue:
novo thread (novo runnable () {@Override public void run () {System.out.println (thread.currentThread (). getid ());}}). start ();Se você escrever muito, não é chato? As regras de escrita baseadas em lambda tornam -se concisas e claras, da seguinte forma:
novo thread (() -> system.out.println (thread.currentThread (). getId ())). start ();
Preste atenção aos parâmetros do thread. A implementação anônima do Runnable é implementada em uma frase e é escrita como a seguinte para entender melhor.
Runnable r = () -> system.out.println (thread.currentThread (). GetId ());
novo thread (r) .start ();
Obviamente, o objetivo de Lambda não é apenas escrever de forma concisa, mas resumir o objetivo de nível superior depois de entendê-lo.
Vejamos outro exemplo de comparador. De acordo com o método tradicional de escrita, como segue:
Inteiro [] a = {1, 8, 3, 9, 2, 0, 5}; Arrays.sort (a, novo comparador <Teger> () {@Override public int (compare (Inteiro O1, Inteiro O2) {retorna o1 - o2;}});As expressões lambda são escritas da seguinte forma:
Inteiro [] a = {1, 8, 3, 9, 2, 0, 5};
Arrays.sort (a, (o1, o2) -> o1 - o2);
Interfaces funcionais no JDK
Para que a biblioteca de classes existente use diretamente as expressões Lambda, havia algumas interfaces no Java 8 que foram marcadas como interfaces funcionais:
Um novo pacote java.util.function foi adicionado ao Java 8, trazendo a interface funcional comumente usada:
In addition, more specific functions are added to the processing of basic types, including: BooleanSupplier, DoubleBinaryOperator, DoubleConsumer, DoubleFunction<R>, DoublePredicate, DoubleSupplier, DoubleToIntFunction, DoubleToLongFunction, DoubleToLongFunction, DoubleUnaryOperator, IntBinaryOperator, IntConsumer, IntFunction<R>, IntPredicate, IntSupplier, IntToDoubleFunction, IntToLongFunction, IntUnaryOperator, LongBinaryOperator, LongConsumer,LongFunction<R>, LongPredicate, LongSupplier, LongToDoubleFunction,LongToIntFunction, LongUnaryOperator, ToDoubleBiFunction<T, U>, ToDoubleFunction<T>,ToIntBiFunction<T, U>, ToIntfunção <T>, TolongBifunction <T, U>, Tolongfunção <T>. Combinado com as interfaces funcionais acima, você pode ver o papel da interface rapidamente através do nome da classe dessas interfaces funcionais básicas.
Crie uma interface funcional
Às vezes, precisamos implementar uma interface funcional e o método é muito simples. Primeiro, você deve garantir que essa interface possa ter apenas uma operação de função e anote o @functionalInterface no tipo de interface.
Derivação do tipo
A derivação do tipo é a base das expressões lambda, e o processo de derivação do tipo é o processo de compilação das expressões lambda. O código a seguir é um exemplo:
Função <string, número inteiro> strToint = str -> integer.parseint (str);
Durante a compilação, o processo de derivação do tipo que eu entendo é o seguinte:
O tipo de destino aqui é a chave e a assinatura do método é obtida através do tipo de destino e a compara com a expressão Lambda.
Referência do método
A base da referência do método (referência do método) também é uma interface funcional, que pode ser implementada diretamente como uma interface funcional, tem a mesma função que as expressões Lambda e também depende da derivação do tipo. As referências de método podem ser vistas como simplificação das expressões lambda que chamam apenas um método.
A sintaxe mencionada pelo método é: TIPO :: MethodName ou InstanceName :: MethodName, e o nome do método correspondente ao construtor é novo.
Por exemplo, os exemplos foram usados acima:
Função <string, número inteiro> strToint = str -> integer.parseint (str);
A referência de método correspondente é
Função <string, número inteiro> strtoint = inteiro :: parseint;
De acordo com o tipo de método, as referências de método são divididas principalmente nos seguintes tipos: referência do método construtor, referência de método estático, referência do método da instância na instância, referência do método da instância no tipo, etc.
Referência do método do construtor
A sintaxe é: tipo :: novo. Por exemplo, a seguinte função é converter uma string em uma matriz
Escrita de referência do método
Função <string, número inteiro> strtoint = inteiro :: new;
Lambda escrevendo
Função <string, número inteiro> strToint = str -> novo inteiro (str);
Escrita tradicional
Function <string, número inteiro> strtoint = new function <string, inteiro> () {@Override public integer Aplicar (string str) {return new Integer (str); }};
Referência do construtor da matriz
A sintaxe é: tipo [] :: novo. Por exemplo, a seguinte função é construir uma matriz de string de comprimento especificado
Escrita de referência do método
Função <inteiro, string []> fixoRray = string [] :: new;
Escrita de referência do método
Função <número inteiro, string []> fixoRray = length -> new String [comprimento];
Escrita tradicional
Função <integer, string []> fIllArray = nova função <Inteiro, String []> () {@Override public String [] Aplicar (comprimento inteiro) {return string [comprimento]; }};Referência de método estático
A sintaxe é: tipo :: novo. Como a função a seguir também é usada para converter strings em matrizes
Escrita de referência do método
Função <string, número inteiro> strtoint = inteiro :: parseint;
Lambda escrevendo
Função <string, número inteiro> strToint = str -> integer.parseint (str);
Escrita tradicional
Função <string, número inteiro> strToint = new function <string, inteiro> () {@Override public integer Aplicar (string str) {return integer.parseint (str); }};Referência do método da instância em uma instância
A sintaxe é: InstanceName :: MethodName. Por exemplo, a função de julgamento a seguir é usada para determinar se o nome fornecido existe na lista
List <string> nomes = Arrays.asList (new String [] {"Zhang San", "Li Si", "Wang Wu"});
Predicado <string> checkNameExists = names :: contém;
System.out.println (checkNameExists.test ("Zhang San"));
System.out.println (checkNameExists.test ("zhang si"));
Referência do método da instância no tipo
A sintaxe é: TIPO :: MethodName. Referência de tempo de execução refere -se a um objeto no contexto, como a função abaixo para retornar o comprimento da string
Function <string, integro> calcstrlength = string :: length; system.out.println (calcstrlength.apply ("zhang san")); list <string> names = arrays.asList (new string [] {"zhangsan", "lisi", "wangwu"}); (names.tream.
Por exemplo, a função a seguir especificou um separador para dividir a string em uma matriz
Bifunction <string, string, string []> split = string :: split;
String [] nomes = split.apply ("zhangsan, lisi, wangwu", "");
System.out.println (Arrays.toString (nomes));
Objetos de fluxo
conceito
O que é fluxo? O fluxo aqui é diferente do InputStream e do OutputStream em IO. O fluxo está localizado no pacote java.util.stream e também é adicionado recentemente ao Java 8. O fluxo é apenas um conjunto de elementos que suportam operações de agregação paralela serial, que podem ser entendidas como uma versão aprimorada de uma coleção ou iterador. O que é uma operação de agregação? Para dar um exemplo simples, os comuns incluem média, máxima, mínima, soma, classificação, filtragem etc.
Vários recursos do fluxo:
Processamento único. Após a conclusão de um processamento, o fluxo atual é fechado.
Apoie maneiras comuns de obter fluxos em operações paralelas
Receba da coleção
Coleção.stream ();
Coleção.parallelStream ();
Fábrica estática
Arrays.stream (matriz)
Stream.of (t…)
Intstream.Range ()
Aqui, apenas daremos uma breve introdução ao fluxo e haverá aplicativos específicos abaixo. Se você quiser falar sobre o relacionamento entre as expressões de fluxo e Lambda, na verdade não há relacionamento particularmente próximo. Só que as expressões Lambda facilitam bastante o uso do fluxo. Sem expressões lambda, um grande número de classes anônimas será gerado durante o uso do fluxo, o que é muito estranho.
Dê um exemplo
As demos a seguir dependem do objeto do funcionário e do objeto List composto pelo objeto do funcionário.
Public classe funcionário {nome da string privada; sexo privado de cordas; private Int Age; funcionário público (nome da string, sexo de string, idade) {super (); this.name = nome; this.sex = sexo; this.age = idade; } public string getName () {return name; } public string getSex () {return Sex; } public int getage () {Age de retorno; } @Override public String tostring () {StringBuilder Builder = new StringBuilder (); construtor.Append ("funcionário {name ="). Append (nome) .append (", sex ="). Anexe (sexo) .append (", AGE ="). Append (Age) .Append ("}"); retornar construtor.toString (); }} List <cômio> funcionários = new ArrayList <> (); funcionários.Add (novo funcionário ("Zhang San", "Masculino", 25)); funcionários. funcionários.Imprima todos os funcionários
A coleção fornece o método foreach para operarmos objetos individuais um por um.
funcionários.foreach (e -> System.out.println (e));
ou
funcionários.stream (). foreach (e -> system.out.println (e));
Classificar por idade
Coleções.sort (funcionários, (e1, e2) -> e1.getage () - e2.getage ());
funcionários.foreach (e -> System.out.println (e));
ou
funcionários.stream (). classificado ((e1, e2) -> e1.getage () -e2.getage ()). foreach (e -> system.out.println (e));
Imprima a funcionária mais antiga
Max/min retorna o maior elemento/min em condições de classificação especificadas
Funcionário maxageFemaleEmployee = funcionários.Stream () .Filter (e -> "feminino" .Equals (e.getSex ())) .max ((e1, e2) -> e1.getage () -e2.getage ().
Imprima funcionários do sexo masculino com mais de 20 anos
filtra os elementos que atendem aos critérios
Funcionários.stream ()
.Filter (e -> e.getage ()> 20 && "masculino" .equals (e.getSex ()))
.foreach (e -> System.out.println (e));
Imprima os dois funcionários mais antigos do sexo masculino
O método limite intercepta elementos limitados
funcionários.Stream () .Filter (e -> "masculino" .Equals (e.getSex ())).
Imprima os nomes de todos os funcionários do sexo masculino, use, separado
Mapa para formar um novo fluxo após a execução da função fornecida.
String maleemployeeesNames = funcionários.stream () .map (e -> e.getName ()) .Collect (colecionors.Joining (",", ");Informações estatísticas
IntsummaryStatistics, DoublesMaryStatistics, LongSummaryStatistics contém os dados de resumo no fluxo.
Intsummarystatistics stat = funcionários.stream () .maptoint (funcionário :: getage) .summaryStatistics (); system.out.println ("Número total de funcionários:" + stat.getCount ()); System.out.println ("idade máxima:" + stat.getMax ()); System.out.Println ("Agexium:" + sTATMax ()); System.out.Println ("máxima": + sTAT.getMax ()); System.out.Println ("máxima": + sTAT.getMax ()); System.out.Println ("Máximo". stat.getmin ()); system.out.println ("idade média:" + stat.getAverage ());Resumir
As expressões Lambda podem realmente reduzir muito código e melhorar a produtividade. Obviamente, existem desvantagens, isto é, expressões complexas serão pouco legíveis, ou pode ser porque elas não estão muito acostumadas. Se você se acostumar, acredito que você vai gostar. Tudo tem dois lados, depende de como equilibramos os prós e os contras, especialmente em uma equipe.
O exposto acima está a informação que classifica Java8 Javalambda. Continuaremos a adicionar informações relevantes no futuro. Obrigado pelo seu apoio a este site!