O mínimo que você deve saber de Java 8

Depois de anos de espera, o Java 8 tem sua versão final disponível para download!

Na Caelum trabalhamos há algum tempo com a versão beta do Java 8. É por esse motivo que nosso curso de Java básico já se encontra atualizado, com uma seção de classe anônimas e lambdas, além de seu uso em outras APIs. Também escrevemos um livro de Java 8 e a na nossa carreira Java Júnior da plataforma Alura.

Esse post escrito em 2014, foi atualizado agora nesse ano de 2017 com novos links, formatação e conteúdo

São muitas as novidades e sumarizamos aqui as principais modificações na linguagem e na API. Vamos direto a um código para enxergar os três principais novos conceitos da linguagem.

Ordenando coleções

Dada uma lista de Strings:

List<String> palavras = Arrays.asList("rodrigo", "paulo", "caelum");

Queremos ordená-la de acordo com o tamanho de cada String. Para isso criamos um Comparator através de uma classe anônima, como já estamos habituados:

Comparator<String> comparador = new Comparator<String>() {
  public int compare(String s1, String s2) {
    return Integer.compare(s1.length(), s2.length()); 
  }
}

E em seguida utilizamos o Collections.sort para ordenar a lista com o critério de comparação definido:

Collections.sort(palavras, comparador);

A primeira novidade do Java 8 é que podemos fazer essa chamada desta forma:

palavras.sort(comparador);

Sim, há um novo método em java.util.List, que é o sort. Por que não fizeram antes? Pois adicionar métodos novos em uma interface pode quebrar muito código já existente em quem implementa List. E o que tem de diferente no Java 8?

Conhecendo os default methods

Abrindo o código da interface List podemos ver como é o sort:

    default void sort(Comparator<? super E> c) {
        Collections.sort(this, c);
    }

Podemos ter métodos concretos em interfaces a partir do Java 8! Basta utilizar o modificador default. Eles serão ‘herdados’ por todos que implementarem essa interface.

Esse recurso, chamado default method, permite evoluir uma interface sem quebrar compatibilidade. É uma técnica já bem conhecida no C#, Scala e outras linguagens.

Há muitos outros métodos default que foram adicionados a API de coleções, como Collection.removeIf, Map.getOrDefault e até mesmo no Comparator, como o Comparator.reversed, que devolve um novo comparador que ordena ao contrário.

Expressão Lambda

Além de ficar mais prático de escrever o código sem o uso direto da Collections, podemos também criar o Comparator de maneira bem mais enxuta sem utilizar a sintaxe de classe anônima:

Comparator<String> comparador = (s1, s2) -> {
  return Integer.compare(s1.length(), s2.length()); 
};

Essa é a sintaxe do Lambda no Java 8. Ela pode ser utilizada com qualquer interface funcional. Uma interface funcional é aquela que possui apenas um método abstrato (semanticamente falando pode haver diferenças).

Dessa forma o compilador consegue inferir qual método está sendo implementado nessas linhas. Diferente da geração de classes em tempo de compilação, como é feito para as classes anônimas, o lambda do Java 8 utiliza MethodHandles e o invokedynamic.

Reduzindo mais ainda o código

O código pode ficar ainda mais enxuto. Como há apenas uma instrução dentro desse lambda, não precisamos nem do return, nem do uso das chaves:

Comparator<String> comparador = (s1, s2) -> 
  Integer.compare(s1.length(), s2.length()); 

Ou ainda passar tudo isso diretamente como argumento para o sort:

palavras.sort((s1, s2) -> Integer.compare(s1.length(), s2.length()));

Você pode utizar o lambda em qualquer interface antiga que seja considerada funcional:

new Thread(() -> System.out.println("thread nova rodando")).start();

Como um dos construtores de Thread recebe uma interface funcional, o compilador sabe que deve tentar converter esse lambda para um Runnable! É sempre necessário o envolvimento de uma interface funcional. O seguinte código não compila:

Object o = () -> System.out.println("thread nova rodando");

Compilaria se tivéssemos declarado como um Runnable.

Muitos dos novos métodos inseridos nas interfaces das collections recebem um argumento que é uma interface funcional, como o Collection.forEach:

palavras.forEach(s -> System.out.println(s));

O forEach recebe um Consumer como argumento, que é uma das muitas novas interfaces do pacote java.util.function. Ele tem apenas um método, o accept, que recebe T e não devolve nada. Como o método recebe apenas um argumento, repare que não foi necessário declarar s entre parenteses no lambda s -> System.out.println(s).

Ordenando as coleções com a expressão lambda

Podemos fazer a nossa ordenação ficar ainda mais sucinta. Interfaces podem ter métodos default estáticos, agrupando melhor métodos utilitários. O Comparator possui o factory method comparing.

Ele recebe uma Function que, no nosso caso, recebe uma String e devolve algo que queiramos usar como critério de comparação. Vamos passar um lambda que, dado a String, devolve seu length:

palavras.sort(Comparator.comparing(s -> s.length());

Escrevendo a expressão lambda com method reference

É muito comum um lambda simplesmente invocar um único método. Um lambda também pode ser escrito como forma de method reference. Em vez de s -> s.length() fazemos simplesmente String::length, ficando implícito que queremos, para a String passada como argumento, que o length seja invocado:

palavras.sort(Comparator.comparing(String::length);

Isso é possível pois as duas linhas a seguir são equivalentes:

Function<String, Integer> function = s -> s.length();
Function<String, Integer> function = String::length;

A segunda é até mais fácil para o compilador inferir, já que algumas vezes pode haver ambiguidade e a necessidade de tipar os argumentos do lambda, como (String s) -> s.length(). E você poderia passar essa function como argumento para o Comparator.comparing, mas obviamente é desnecessário, pois podemos passar diretamente o lambda, como fizemos.

Para aplicar um filtro nessa lista, como por exemplo retornar apenas as palavras com menos de 6 caracteres, gostaríamos de fazer algo como palavras.filter(...). Porém o método filter não foi adicionado em nossa API de Collection!

Existem várias razões para isso, como não querer misturar métodos sem efeitos colaterais em coleções mutáveis, além de evitar deixar as coleções muito poluídas com tantas novas funcionalidades.

Aumentando o poder com Stream

Para fazer essa e outras transformações comuns em nossas coleções, contamos agora com uma nova API, o Stream.

Para criar um Stream com os elementos de nossa lista só precisamos chamar o método defaut .stream() presente na interface Collection (e em outros lugares!). Fazemos palavras.stream() para ter um Stream.

Essa API traz uma forma mais funcional de trabalhar com nossas coleções. Ela possui diversos métodos, como o filter, map e reduce, que recebem uma interface funcional como parâmetro, nos possibilitando tirar proveito dos novos recursos de lambda e method reference.

Filtrando coleções

Para filtrar as Strings com menos de 6 caracteres em nossa lista podemos fazer:

palavras.stream()
	.filter(s -> s.length() < 6)
	.forEach(System.out::println);

O método filter recebe a interface funcional Predicate como parâmetro. Essa interface possui apenas o método test que recebe T e retorna um boolean. Você nem precisava saber disso! Com o lambda, os nomes das interfaces funcionais perdem um pouco a importância e tornam o código mais simples de ler.

Utilizando o map

Outro método que será muito utiizado em nosso dia a dia é o map, podemos e devemos utilizá-lo quando precisamos aplicar transformações em nossa lista sem a necessidade de variáveis intermediárias. Para mapear as palavras pelo seu tamanho (length), podemos fazer:

Stream<Integer> stream = palavras.stream().map(String::length);

Porém recebemos um Stream<Integer> como retorno. Para evitar esse boxing desnecessário dos tipos primitivos a API de Streams possui implementações equivalentes ao %%Stream%% para eles: IntStream, LongStream, e DoubleStream. Para utilizar um IntStream neste nosso caso, podemos substituir a chamada do método map por mapToInt:

IntStream intStream = palavras.stream().mapToInt(String::length);

Em outros locais é possível evitar o boxing e unboxing. Há em Comparator o método comparingInt que recebe um IntFunction. Podemos fazer aquele sort do inicio do artigo com palavras.sort(Comparator.comparingInt(String::length)).

Mais sobre o Stream

As implementações de Stream para os tipos primitivos possuem diversos métodos para auxiliar na manipulação de seus valores, como é o caso do sum, min, max, count, average, entre diversos outros. O interessante desse ultimo é que o seu retorno será um Optional, outra importante introdução do java 8:

OptionalDouble media = palavras.stream()
	.mapToInt(String::length)
	.average();

System.out.println(media.orElse(0));

Note que o OptionalDouble é a implementação de Optional para esse tipo primitivo, essa estratégia é utilizada em grande parte das novas interfaces!

Voltando ao nosso filtro, vimos que ao fazer palavras.stream().filter(s -> s.length() < 6) isso nos retornou um Stream. Para que o retorno seja uma List contamos com o método collect().

Esse método espera receber a interface funcional Collector como parâmetro. Para simplificar nosso trabalho, já existem diversos factory methods de collectors prontos na classe Collectors, como é o caso do toList():

List<String> resultado = palavras.stream()
	.filter(s -> s.length() < 6)
	.collect(Collectors.toList()); 

Ufa! Esse é um pequeno resumo essencial do que entrou nessa versão.

Se você tiver interesse, pode ver como era a sintaxe proposta para o Java 8 em 2011 nesse antigo post.

Das novidades que ficaram de fora do post, temos o suporte a múltiplas anotações do mesmo tipo, a API de java.time baseada no Joda Time, melhorias na inferência do generics e do operador diamante além de inúmeros ajustes nas APIs.

Muitas features ficaram de fora, como collection literals e value objects. Você pode ver o que entrou e ficou de fora. Mas quem sabe isso tudo não aparece junto com a reificação do generics no Java 9?

81 Comentários

  1. Rafael Dipold 19/03/2014 at 08:31 #

    Não sei se estou ficando velho mas não consigo gostar desses códigos lambdas.

    Claro é sempre bom ter alternativas e não é esse meu ponto, portanto, sejam bem vindo lambdas.

    Mas ao escrever código, mesmo tendo bons conhecimentos em lambdas, daria preferência a códigos mais próximos da linguagem humana, mesmo sendo um pouco mais longo, pois a manutenção tem um custo considerável em qualquer projeto.

  2. Paulo Silveira 19/03/2014 at 09:41 #

    oi Rafael. É uma reacao natural a uma mudança tão forte na linguagem. Essa percepção vai mudar. Lembro que com o generics eu tive o mesmo susto.

    E voce vai ver que o código mais proximo da linguagem humana (na verdade da logica humana) é o lambda. É a matematica. Falar “para cada elemente, caso ele tenha mais de 6 caracteres, coloque-o em uma nova lista” é muito mais estranho que falar “filtre só os que tem mais de 6 caracteres”.

  3. Icaro 19/03/2014 at 11:14 #

    A sintaxe groovy ainda é tao mais limpa…
    Mas o java vai ganhar muito na versao 8

  4. Paulo Silveira 19/03/2014 at 11:17 #

    oi Icaro. Acho que a sintaxe é muito proxima, assim como é proxima da sintaxe do C#. E Java nunca foi famoso por ter uma sintaxe enxuta, nem foi o objetivo da linguagem. Acho que, de maneira geral, ganha-se muito, como voce falou.

  5. Regis 19/03/2014 at 11:43 #

    Realmente tem muita mudança nessa versão do Java 8. E muita gente nem sabe das features do Java 7 ainda . Esses recursos de Lambda e Stream, o java EE 7 na Expression Language 3.0 incluiu um inicio desses recursos.

    Um recurso novo do Java 8 que eu gostei foi a implementação de métodos default . Achei bem interessante isso.

  6. Adilson Bremer 19/03/2014 at 12:54 #

    Tenho acompanhando essas mudanças no Java, e por mais animadoras que sejam, ainda não consigo deixar de pensar sobre como o C#, Groovy, Ruby já fazem isso a bastante tempo, depois de trabalhar com essas linguagens, programar em Java hoje em dia é um pesadelo.

    Infelizmente, atualmente tenho a forte idéia de que Java (a linguagem, não a plataforma) já virou o famoso caso de “Sistema Legado”. (sim, é um pouco de exagero)

  7. Marcelo 19/03/2014 at 13:17 #

    Excelente matéria! Parabéns pela divulgação.

  8. Paulo Silveira 19/03/2014 at 14:26 #

    O Java tem 20 anos de idade. Seria estranho não haver muito codigo legado. Adilson, a escolha do time do Java sempre foi evitar mudancas radicas na linguagem, para não cair no caminho do C++. O C++ adicionou muita novidade, e hoje é uma das linguagens mais difíceis de se dominar. São caminhos diferentes, cada um se encaixa num nicho.

  9. Victor Maehira 19/03/2014 at 14:30 #

    Não vamos mais tomar erro de PermGen Space com o Java 8: http://www.infoq.com/br/news/2013/03/java8-resolvera-permgen

  10. Régis Eduardo Weizenmann Gregol 19/03/2014 at 14:54 #

    Parabéns Paulo Silveira e Rodrigo Turini pelo ótimo post.
    Creio que o mínimo para o start com o Java8 seja isso mesmo. É ótimo e até que enfim uma API descente pra se trabalhar com datas, além do lambda para trabalhar com as listas 🙂

  11. Priscila 19/03/2014 at 19:51 #

    Muito legal Paulo.
    Tenho certeza que é uma grande evolução pro Java. Sempre que era necessário filtrar ou executar funções numa iteração era um código chato de fazer.
    O lambda veio para tornar as coisas mais objetivas e proximas do que precisam ser, e no meu ponto de vista o código fica muito mais enxuto e legível.
    O que ainda continua ruim é q vc precisa trabalhar com diversas classes ainda para executar determinadas iterações, mas ainda tenho esperança de uma evolução nisso. Java estamos com grande ganho no Java 8. Estou trabalhando com scala atualmente, mas não consigo deixar de gostar e torcer por evoluções no java, afinal, é onde comecei.
    O lambda pode parecer estranho pq quebra alguns paradigmas, mas na prática com certeza java ficou um pouco mais produtivo com estas features.
    Parabéns pelo post.

  12. Marcelo Emanoel 20/03/2014 at 10:57 #

    Oi Paulo e Rodrigo. Parabéns por mais um excelente post. O site https://www.java.com ainda está na versão 7u51. Vocês sabem se já existe uma data para disponibilizar um jre 8 para usuários finais? Para nós desenvolvedores já está disponível o jdk 8, mas não posso atualizar ainda minha aplicação a menos que meus usuários também tenham acesso através do jre.
    Abraço

  13. Paulo Silveira 20/03/2014 at 11:39 #

    oi Marcelo

    Acho que no java.com deve mudar no dia 25, que eles vão fazer uma divulgação forte da nova versão!

  14. Raphael Lacerda 20/03/2014 at 14:56 #

    Excelente Post! E o livro está ainda melhor!

    Impressionante o quanto que mudou dos releases beta

  15. Arthur Carvalho 21/03/2014 at 16:26 #

    É sempre tão emocionante testar novos formatos código… Dá sempre a impressão que não vai compilar mas compila e executa lindamente. Muito feliz com as novas features do Java 8, espero poder trabalhar com ele em breve. Quanto tempo acha que demora pra o Android adota-lo?

    Ótimo post, obrigado!

  16. Paulo Silveira 21/03/2014 at 16:28 #

    oi arthur. acho que android demora um pouco, mas google costuma ser rápido né?

  17. Marcus Almeida 21/03/2014 at 16:49 #

    Vendo esse recurso Lambda (proveniente das linguagens funcionais) dá uma impressão de que o Java vai incorporando algumas caracteristicas do Scala. Isso é excelente.

  18. Wilson 23/03/2014 at 20:30 #

    Belo post Paulo e Rodrigo, simples e direto.
    Um abraço!

  19. Marcos Paulo 24/03/2014 at 09:40 #

    Acho que é só eu em que vivo no mundo real! vamos sair da “Matrix”, no meu ponto de vista o java é uma excelente linguagem e plataforma mas poderia melhorar ainda mais como por exemplo o desenvolvimento para desktop hoje existe um monte de tranqueira para fazer-mos a mesma coisa; e as IDES que tal melhorarem; Padronizar é o caminho!

  20. Julio Santana 25/03/2014 at 16:08 #

    Olá Paulo / Turini, Excelente post, estou agora lendo o livro -Java 8 Prático: Lambdas, Streams e os novos recursos da linguagem, e cada vez fico mais entusiasmado com os aspectos positivos que trouxeram essas mudanças. Parabéns pelo post e também pelo livro!

  21. André Willik Valenti 02/04/2014 at 17:59 #

    Legal a sequência do post! Partiram de um exemplo para explicar cada uma das novidades, que estão bem interessantes!

    Lá no começo, tem uma parte que acredito estar errada: pelo menos até o Java 7, não se pode ordenar diretamente uma Arrays.asList(…), pois essa lista é imutável. É preciso fazer new ArrayList(Arrays.asList(…)). Podem dar uma verificada?

    []s,
    André

  22. Paulo Silveira 02/04/2014 at 18:36 #

    ola Andre! Que bom que gostou.

    Pois é. Eu tambem sempre usava a frase “asList devolve lista imutavel” e isso não é bem verdade. Ele devolve uma lista backedup pela array dada. Em outras palavras, você não pode adicionar/remover elementos, mas os elementos da lista (na verdade da array por tras dela) são mutaveis sim, você pode invocar o método set. Esse método basta para Collections.sort, entao esse código funciona perfeitamente.

  23. Jean 04/04/2014 at 10:17 #

    Troquei java por python, mais enxuto, direto e muito, muito potente!!!

  24. Marcos W. Ferretti 04/04/2014 at 13:33 #

    Interessante, o C# foi um clone do java e nasceu com muitas melhorias, inclusive estas expressões lambdas. Agora o Java ta clonando o C#. kkk

    Também troquei o java/c# por PYTHON, não tenho palavras para expressar o quanto me sinto feliz com isso!! rsrs…

    Dalhe python!!!!

  25. Emmanuel Ramos 17/04/2014 at 12:29 #

    Tendo em vista que no Java Efetivo o Bloch não recomenda “muito” o uso de classes abstratas, e sim interfaces, agora com o default method: adiós abstract, é isso mesmo? 🙂

  26. Samuel Deschamps 23/04/2014 at 00:01 #

    Parabéns pelo artigo! Bastante fácil de entender. Agora pretendo evangelizar o Java 8 na minha empresa. Me assustei um pouco com a sintaxe do lambda mas gostei. É só usar um pouco que vc se acostuma.

  27. Eduardo 27/04/2014 at 23:49 #

    Acho que o Paulo anda lendo “O mínimo que você precisa saber para não ser um idiota” do Olavo de Carvalho…rs

  28. Daniel Frank 07/05/2014 at 08:58 #

    Ótimo artigo.
    Só não consegui entender a lógica de ser Comparator#comparing ao invés de Comparators#comparing, se olharmos os outros “Factory Methods” presentes no artigo, os mesmos utilizam esse padrão, vide Colectors#toList.

  29. Alexei Dimitri Diniz Campos 27/06/2014 at 00:23 #

    Eu acredito que a sintaxe lambda em Java seja um retrocesso, não um avanço.

    Toda vez que você faz algo em que haja pré-suposição, como percebo ser a característica fundamental dessa sintaxe, você está tornando o trecho de código dependente de um contexto, que muitas vezes, é o próprio programador. Significa que o código se tornará menos legível por outros e consequentemente, tornará a manutenção um terror.

    Como notou nosso caro colega acima, isso tornaria Java muito próximo de linguagens de script, tais como Perl e Python, que são a meu ver horríveis e anti-naturais.

    No caso de Generics, ela fez o contrário: tornou um contexto genérico específico, ou seja: antes, o compilador não era capaz de inferir o que se podia colocar num collection, nem podia sequer impedir o programador de fazê-lo: desde a java 5, agora ele pode fazê-lo e impedir, se for necessário.

    A força de Java está em ser uma linguagem de fácil manutenção e baixa dependência de contexto: semântica explícita. Sem essas características, perderá utilidade, pois PHP e Ruby possuem desempenho bem melhor (com os mesmos recursos computacionais) .

  30. Paulo Silveira 27/06/2014 at 01:24 #

    é uma opiniao válida Alexei. por esse motivo eles optaram por criar os lambdas de maneira menos intrusiva possível, mesmo assim intrusiva. sobre a legibilidade, acho que com pouco tempo a impressao muda. vamos ver.

  31. Marcos Rodrigues 16/07/2014 at 11:51 #

    Quanto aos lambdas, nada a reclamar, acho lambdas muito produtivos. Mas, uma questão que eu vi em um livro da Casa do Código, e que me fez ficar confuso.

    Até o Java 7, eu poderia fazer um forEach da seguinte maneira:
    for(Pessoas p : listPessoas){
    //faça algo
    }

    No Java 8, parece que ficou mais complexo. Eu teria de usar da seguinte maneira (não usando lambdas)
    listPessoas.forEach(new Consumer(){
    private void accept(Pessoas p){
    //faça algo
    }
    });

    Por que eu deveria usar o forEach de um Collection, sendo que está muito mais complicado (Sem lambdas), do que usar um forEach clássico, usado até o Java 7 ?!

  32. Paulo Silveira 16/07/2014 at 13:30 #

    Sem o lambda não faz tanto sentido usar o forEach, mas ainda assim há uma vantagem: chamando o parallelStream você pode paralelizar tudo. e também pode reaproveitar o Consumer, caso faça sentido.

  33. Bruno 01/08/2014 at 16:42 #

    Vocês vão-me desculpar mas assim o Java não irá fazer a diferença entre as outras linguagens de programação.
    Assim está a perder a diferenciação, para alem de complicar o que é simples. Nem sempre são precisas modificações.

  34. Bruno 01/08/2014 at 16:45 #

    Gostava de saber se o Java 8 suporte a sintaxe do Java 7, ou seja se da para implementar sem lambdas? Vai dar das duas maneiras ?

  35. Paulo Silveira 01/08/2014 at 19:15 #

    sim. é compativel toda a sintaxe anteriora!

  36. Paulo Silveira 01/08/2014 at 19:16 #

    Bruno, é natural parecer uma complicação a primeira vista. Eu também senti isso quando entrou o generics. Com o tempo poderemos observar se essas mudanças sao realmente complicadas ou se eram desnecessárias. Ao meu ver, elas sao bem vindas.

  37. Bruno 03/08/2014 at 11:47 #

    Na minha opinião ta-se a criar redundância no Java. veja-mos um exemplo: A collections usamos para manipular listas. Essas listas usamos para acessar aos dados. Então agora vamos também poder manipular directamente com listas?
    Qual a vantagem, para alem de estar-mos a quebrar regras de interfaces. Só porque podemos criar um comparador de uma forma mais curta ? (lambda) !

    Diferença: Collections.sort(listax); listax.sort(comparador);

    Não vejo muita vantagem nisso.

    Obrigado Paulo Silveira, pelos esclarecimentos.
    Sou de Portugal.

  38. Bruno 03/08/2014 at 12:14 #

    Qual a vantagem ?

    lista.forEach( s -> System.out.println(s));

    lista.forEach( System.out::println);

    Daqui a nada, não escreve-mos nada e o objectivo não seria esse, mas descomplicar conceitos que no java ainda são muito confusos em relação ao C# por exemplo.

    Paulo, desculpa lá mas não existe vantagem nisto.

  39. Bruno 03/08/2014 at 12:37 #

    O Paulo tem razão numa coisa que diz. É verdade que o monstro inicial de comparador ficou bem mais curto. O problema é que utilizadores do Java vão utilizar isso sem saber o que realmente está por traz. E isso nunca deve acontecer num programador. E da forma antiga para implementar tinhas de perceber o que realmente funcionava por traz.

    🙂 mas aceito e sei que vou usar, por ser muito curioso.

  40. Bruno 03/08/2014 at 13:12 #

    /*
    * To change this license header, choose License Headers in Project Properties.
    * To change this template file, choose Tools | Templates
    * and open the template in the editor.
    */

    package teste;

    import java.util.Arrays;
    import java.util.List;

    /**
    *
    * @author gusto
    */
    public class Teste {

    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) {

    List lista = Arrays.asList(“gusto”,”paulo”,”rosa”, “manuel”);
    System.out.println(lista);

    lista.removeIf((String x) -> x.endsWith(“el”));
    System.out.println(lista);

    }
    }

  41. Bruno 03/08/2014 at 13:13 #

    Paulo qual o erro na nova sintaxe do Java?
    Isto da-me erro.

    Obrigado

  42. Bruno 03/08/2014 at 13:40 #

    paulo qual a vantagem que ves neste codigo ?

    public static void main(String[] args) {

    List lista = Arrays.asList(“gusto”, “paulo”, “rosa”, “manuel”);

    lista.forEach((String s) -> {
    if (s.endsWith(“to”)) {

    System.err.println(s);
    } else {

    System.out.println(“nao tem”);
    }
    });
    System.out.println(lista);

    for (String s : lista) {

    if(s.endsWith(“to”)){

    System.err.print(s);
    }else{

    System.out.println(“nao tem”);
    }
    }
    }

    }

  43. Bruno 03/08/2014 at 18:51 #

    As IDE, ainda não estão preparadas para estas situações. Veja-mos o Netbeans:

    private void initComponents() {

    botao = new javax.swing.JButton();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    botao.setText(“Botao”);

    botao.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
    botaoActionPerformed(evt);
    }
    });

  44. Rodrigo Turini 04/08/2014 at 09:51 #

    Oi Bruno! Não é redundância, mas sim retro compatibilidade. O Java não quebra compatibilidade entre versões, você ainda pode usar recursos das versões anteriores ainda que usando a mais atual.

    Pra mim a vantagem é clara. Da uma olhada nesse código:

    Collections.sort(usuariosFiltrados, new Comparator&lt;Usuario&gt;() {
    	public int compare(Usuario u1, Usuario u2) {
    		return u1.getNome().compareTo(u2.getNome());
    	}	
    });
    

    É bastante verboso e nem um pouco flexível. Com Java 8 você faz:

    usuarios.stream().sorted(comparing(Usuario::getNome));
    

    Mas claro, é uma syntax nova, recursos novos… leva um tempo pra se adaptar.

  45. Rodrigo Turini 04/08/2014 at 09:59 #

    Bruno, quanto ao código que você mandou e não estava compilando,
    faltou inferir o Generics da lista (List). O código fica assim:

    public static void main(String[] args) {
    List<String> lista = Arrays.asList("gusto", "paulo", "rosa", "manuel");
    System.out.println(lista);
    lista.removeIf((String x) -> x.endsWith("el"));
    System.out.println(lista);
    }

    Um detalhe, você pode deixar seu código ainda mais simples fazendo o lambda assim:

    lista.removeIf( x -> x.endsWith("el"));

    Como é uma lista da String, o java vai inferir o tipo pra você.

  46. Rodrigo Turini 04/08/2014 at 10:03 #

    Quanto as IDEs, as mais utilizadas do mercado já estão trabalhando bem com Java 8. NetBeans, Eclipse e Intellij são algumas que já testamos e funciona muito bem.

    Obs: Esse código que você mandou não usa nenhum recurso do Java 8. Confere se sua IDE está bem configurada. Um abraço

Deixe uma resposta