No Java 8 quais foram os principais recursos introduzidos?

Tempo de leitura: 9 min

Escrito por Michel Adriano Medeiros
em 29/11/2023

Java 8

Java 8

O lançamento do Java 8 foi um marco significativo no mundo da programação, introduzindo uma série de recursos e novidades que revolucionaram a forma como os desenvolvedores escrevem código. Uma das mudanças mais impactantes foi a introdução das Expressões Lambda e da Stream API.

As Expressões Lambda trouxeram uma nova maneira de escrever código conciso e legível, permitindo a passagem de funcionalidades como parâmetros e simplificando a implementação de interfaces funcionais. Essa capacidade de escrever funções anônimas de forma mais sucinta abriu portas para a criação de códigos mais flexíveis e orientados a funcionalidades.

Juntamente com as Lambdas, veio a Stream API, que revolucionou a manipulação de coleções de dados. Essa API oferece métodos poderosos para operações de filtragem, mapeamento, redução e muito mais, permitindo o processamento de grandes volumes de dados de forma eficiente e elegante.

Além disso, a introdução da Interface Funcional, que permite a definição de interfaces com apenas um método abstrato, foi fundamental para o sucesso das Lambdas. Os Default Methods e Métodos Estáticos em Interfaces expandiram ainda mais a flexibilidade das interfaces, permitindo a adição de métodos concretos sem quebrar a compatibilidade com implementações existentes.

A classe Optional proporcionou uma maneira mais segura de lidar com valores nulos, reduzindo significativamente os erros relacionados a NullPointerException.

A Date and Time API trouxe melhorias na manipulação de datas e horários, oferecendo classes imutáveis como LocalDate, LocalTime, LocalDateTime e ZonedDateTime, simplificando operações de manipulação de tempo e facilitando cálculos de diferenças entre datas.

O forEach() method, presente na Stream API, tornou a iteração em coleções mais eficiente e legível, possibilitando a execução de ações específicas em cada elemento da coleção.

As Method References, ou Referências a Métodos, permitem referenciar métodos existentes usando um atalho, proporcionando uma sintaxe mais limpa e elegante.

Além disso, o Java 8 introduziu o CompletableFuture para processamento assíncrono, simplificando tarefas que requerem execução paralela e tratamento de futuros.

A inclusão do Nashorn JavaScript Engine ofereceu a capacidade de executar scripts JavaScript diretamente no Java, ampliando as possibilidades de integração entre as linguagens.

Todas essas novidades contribuíram para melhorias significativas de desempenho, além de proporcionar aos desenvolvedores ferramentas poderosas para escrever código mais conciso, legível e eficiente. O Java 8 representou uma evolução marcante na linguagem, abrindo caminho para o paradigma funcional e tornando o desenvolvimento em Java mais flexível e poderoso.

Funções Lambda

Funções lambda no Java são uma maneira concisa de criar implementações de interfaces funcionais. Elas permitem que você escreva código mais sucinto ao passar blocos de código como argumentos para métodos ou para expressar operações de maneira mais simples e direta.

A ideia principal das funções lambda está intimamente ligada ao conceito de interfaces funcionais, que são interfaces que contêm um único método abstrato. O Java utiliza essas interfaces como base para as funções lambda.

A sintaxe das funções lambda no Java segue este formato básico:

Aqui está um exemplo simples para ilustrar:

Suponha que você tenha uma interface funcional Calculadora com um único método calcular que recebe dois inteiros e retorna um resultado:

Antes do Java 8, você teria que criar uma classe anônima para implementar essa interface:

Com funções lambda, você pode fazer isso de forma muito mais concisa:

Isso é equivalente à implementação da interface Calculadora para realizar a soma de dois números. As funções lambda permitem que você reduza a verbosidade do código ao escrever implementações simples de interfaces funcionais.

Além disso, as funções lambda podem ser passadas como argumentos para métodos de maneira mais elegante, facilitando o uso de expressões mais compactas em operações como filtragem de listas, mapeamento de elementos, entre outras.

É importante notar que as funções lambda no Java são úteis principalmente em situações em que se faz necessário o uso de interfaces funcionais, tornando o código mais legível, conciso e expressivo.

Stream API

A Stream API no Java é uma poderosa ferramenta introduzida a partir do Java 8 para manipular coleções de elementos de maneira mais eficiente, concisa e funcional. Ela permite realizar operações de processamento de dados de forma declarativa, facilitando o trabalho com coleções como listas, conjuntos, mapas, entre outros.

Em termos simples, uma Stream é uma sequência de elementos que suporta uma variedade de operações para realizar transformações e processamento de dados. Ela não é uma estrutura de dados em si, mas sim uma sequência de elementos que pode ser obtida a partir de uma coleção existente.

A Stream API permite executar operações em coleções de dados de maneira eficiente, utilizando operações de pipeline. As principais características da Stream API incluem:

  1. Operações de pipeline: As operações da Stream são divididas em duas categorias: operações intermediárias e operações terminais. As operações intermediárias (como map(), filter(), sorted(), distinct(), entre outras) são aquelas que retornam uma nova Stream e podem ser encadeadas para formar uma sequência de operações. Já as operações terminais (como collect(), forEach(), reduce(), count(), anyMatch(), allMatch(), noneMatch(), entre outras) são aquelas que produzem um resultado final e encerram o pipeline da Stream.
  2. Processamento lazy (preguiçoso): As operações em uma Stream podem ser lazy, o que significa que elas são executadas apenas quando uma operação terminal é chamada. Isso permite otimizações, como evitar processamento desnecessário de elementos.
  3. Programação funcional: A Stream API utiliza conceitos de programação funcional, onde funções lambda podem ser facilmente usadas para expressar operações de forma mais concisa e clara.

Aqui está um exemplo simples de como a Stream API pode ser usada para processar uma lista de números:

Suponha que você tenha uma lista de números:

Você pode utilizar a Stream API para realizar várias operações, como filtrar os números pares, dobrar cada número e depois imprimir os resultados:

Este é um exemplo simples que mostra como a Stream API pode ser usada para realizar operações de filtragem, mapeamento e ação final (impressão) de maneira encadeada e expressiva.

Em resumo, a Stream API no Java proporciona uma forma elegante e funcional de processar coleções de dados, permitindo realizar operações de forma mais eficiente, concisa e declarativa.

https://rinaldo.dev/java-8-streams-pare-de-usar-for-e-simplifique-seu-codigo/

java.time package for date and time

O pacote java.time é uma API introduzida no Java 8 para manipulação de datas, horários, períodos e outras operações relacionadas a tempo. Essa API foi desenvolvida para oferecer uma alternativa mais robusta, flexível e fácil de usar em comparação com as classes mais antigas, como java.util.Date e java.util.Calendar, que eram propensas a problemas de legibilidade, imutabilidade e thread-safety.

Alguns dos principais componentes do pacote java.time incluem:

  1. LocalDate: Representa uma data sem considerar o horário ou fuso horário.
  2. LocalTime: Representa um horário específico sem informações de data.
  3. LocalDateTime: Combina uma data e um horário, sem considerar fuso horário.
  4. Instant: Representa um ponto específico no tempo, em UTC, baseado no padrão Unix Epoch (1º de janeiro de 1970).
  5. Duration e Period: Duration representa um período de tempo baseado em segundos ou nanossegundos, enquanto Period representa um período usando anos, meses e dias, sendo mais apropriado para lidar com diferenças entre datas.
  6. ZoneId e ZoneOffset: ZoneId representa um fuso horário, enquanto ZoneOffset representa um deslocamento fixo em relação ao Tempo Universal Coordenado (UTC).
  7. ZonedDateTime: Combina um LocalDateTime com um ZoneId, representando uma data e hora específicas em um fuso horário específico.
  8. DateTimeFormatter: Permite a formatação e análise de datas e horas em formatos específicos, como “dd/MM/yyyy” ou “HH:mm:ss”.

Essas classes e métodos fornecem funcionalidades para realizar operações de manipulação, formatação, cálculos de diferenças de tempo, além de lidar adequadamente com fusos horários e outras complexidades relacionadas a datas e horários.

Um exemplo simples de utilização da java.time API seria criar uma data atual, formatá-la e exibi-la:

Em resumo, o pacote java.time oferece um conjunto de classes que permitem uma manipulação mais clara, segura e eficiente de datas e horários no Java, abordando muitas das limitações e complexidades encontradas nas versões anteriores das APIs de data e hora.

foreach()

O método forEach() no Java é um método pertencente a várias classes, principalmente à interface Iterable e à interface Stream. Ele é usado para percorrer e aplicar uma ação a cada elemento de uma coleção, como uma lista, um conjunto, um mapa ou uma stream, executando um determinado bloco de código (geralmente expresso por uma expressão lambda ou uma referência a método) para cada elemento da coleção.

Na interface Iterable, o método forEach() permite percorrer cada elemento de uma coleção, realizando uma ação específica para cada um deles. Por exemplo, em uma lista de strings, pode ser usado da seguinte maneira:

Isso imprimiria cada elemento da lista na saída padrão.

Já na interface Stream, o método forEach() é uma operação terminal que permite executar uma ação para cada elemento da stream. Por exemplo:

Aqui, a lista é convertida para uma stream e então o método forEach() é chamado para imprimir cada elemento da lista.

A utilização do forEach() simplifica o código ao percorrer uma coleção sem a necessidade de utilizar um loop tradicional, tornando o código mais conciso e legível. Ele é útil para aplicar operações em cada elemento de uma coleção sem precisar se preocupar com detalhes de índices ou iteração manual.

Vale ressaltar que, ao usar o forEach() em uma stream, por exemplo, o processamento dos elementos pode ser feito de forma paralela, dependendo do tipo de stream utilizado e da natureza da coleção. Isso pode trazer benefícios de desempenho em certos cenários.

Fontes

Curso

https://www.udemy.com/course/curso-java-para-iniciantes/?referralCode=BCDB27D7DF68341BFEE4

Você vai gostar também:

Para enviar seu comentário, preencha os campos abaixo:

Deixe um comentário


*


*


Seja o primeiro a comentar!

Damos valor à sua privacidade

Nós e os nossos parceiros armazenamos ou acedemos a informações dos dispositivos, tais como cookies, e processamos dados pessoais, tais como identificadores exclusivos e informações padrão enviadas pelos dispositivos, para as finalidades descritas abaixo. Poderá clicar para consentir o processamento por nossa parte e pela parte dos nossos parceiros para tais finalidades. Em alternativa, poderá clicar para recusar o consentimento, ou aceder a informações mais pormenorizadas e alterar as suas preferências antes de dar consentimento. As suas preferências serão aplicadas apenas a este website.

Cookies estritamente necessários

Estes cookies são necessários para que o website funcione e não podem ser desligados nos nossos sistemas. Normalmente, eles só são configurados em resposta a ações levadas a cabo por si e que correspondem a uma solicitação de serviços, tais como definir as suas preferências de privacidade, iniciar sessão ou preencher formulários. Pode configurar o seu navegador para bloquear ou alertá-lo(a) sobre esses cookies, mas algumas partes do website não funcionarão. Estes cookies não armazenam qualquer informação pessoal identificável.

Cookies de desempenho

Estes cookies permitem-nos contar visitas e fontes de tráfego, para que possamos medir e melhorar o desempenho do nosso website. Eles ajudam-nos a saber quais são as páginas mais e menos populares e a ver como os visitantes se movimentam pelo website. Todas as informações recolhidas por estes cookies são agregadas e, por conseguinte, anónimas. Se não permitir estes cookies, não saberemos quando visitou o nosso site.

Cookies de funcionalidade

Estes cookies permitem que o site forneça uma funcionalidade e personalização melhoradas. Podem ser estabelecidos por nós ou por fornecedores externos cujos serviços adicionámos às nossas páginas. Se não permitir estes cookies algumas destas funcionalidades, ou mesmo todas, podem não atuar corretamente.

Cookies de publicidade

Estes cookies podem ser estabelecidos através do nosso site pelos nossos parceiros de publicidade. Podem ser usados por essas empresas para construir um perfil sobre os seus interesses e mostrar-lhe anúncios relevantes em outros websites. Eles não armazenam diretamente informações pessoais, mas são baseados na identificação exclusiva do seu navegador e dispositivo de internet. Se não permitir estes cookies, terá menos publicidade direcionada.

Visite as nossas páginas de Políticas de privacidade e Termos e condições.

Importante: Este site faz uso de cookies que podem conter informações de rastreamento sobre os visitantes.
Criado por WP RGPD Pro