Neste artigo damos continuidade à nossa análise histórica sobre os recursos que cada versão do Java trouxe para tornar o código mais limpo e simples para o desenvolvedor.
Se você caiu de paraquedas aqui e ainda não leu a primeira parte, clique aqui.
Java 9
Nesta versão ganhamos métodos para criar coleções, métodos privados em interfaces, novos métodos para Streams API (takeWhile, dropWhile e iterate) e Optional (ifPresentOrElse, or, stream) e melhoria no Try-with-resources.
Novos métodos para criar coleções
Os novos métodos nos permite criar coleções imutáveis com mais facilidade.
// Antes
List<String> lista = Arrays.asList("A", "B", "C");
// Java 9
List<String> lista = List.of("A", "B", "C");
Set<Integer> set = Set.of(1, 2, 3);
Map<String, Integer> mapa = Map.of("um", 1, "dois", 2);
Arrays.asList não era imutável.
Novos métodos para Streams API
O takeWhile serve para pegar elementos de um stream até que a condição seja falsa pela primeira vez.
List<Integer> nums = List.of(1, 2, 3, 4, 5, 6, 7, 8);
List<Integer> resultado = nums.stream()
.takeWhile(n -> n < 5)
.collect(Collectors.toList());
System.out.println(resultado); // [1, 2, 3, 4]
Se a lista não estiver ordenada o takeWhile para na primeira condição de falha.
List<Integer> nums = List.of(1, 2, 6, 3, 4);
List<Integer> resultado = nums.stream()
.takeWhile(n -> n < 5)
.collect(Collectors.toList());
System.out.println(resultado); // [1, 2]
O dropWhile é o oposto do takeWhile. Ele descarta os elementos enquanto a condição for verdadeira.
List<Integer> nums = List.of(1, 2, 3, 4, 5, 6, 7);
List<Integer> resultado = nums.stream()
.dropWhile(n -> n < 5)
.collect(Collectors.toList());
System.out.println(resultado); // [5, 6, 7]
Como no takeWhile, em listas desordenadas o dropWhile para na primeira falha.
List<Integer> nums = List.of(2, 4, 6, 3, 1, 5);
List<Integer> resultado = nums.stream()
.dropWhile(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(resultado); // [3, 1, 5]
O iterate não é novo (veio no pacote do Java 8) mas no Java 9 ganhou uma nova versão com mais um parâmetro.
// Antes
Stream<Integer> numeros = Stream.iterate(1, n -> n + 2)
.limit(5);
numeros.forEach(System.out::println);
// Saída: 1, 3, 5, 7, 9
// Com Java 9
Stream<Integer> numeros = Stream.iterate(
1, // valor inicial
n -> n < 20, // condição de parada
n -> n + 2 // passo
);
numeros.forEach(System.out::println);
// Saída: 1, 3, 5, 7, 9, 11, 13, 15, 17, 19
Novos métodos para Optional
O ifPresentOrElse executa uma função quando o valor do optional está presente ou outra função quando o valor está ausente.
Optional<String> nome = Optional.of("Maria");
nome.ifPresentOrElse(
n -> System.out.println("Olá " + n), // se presente
() -> System.out.println("Valor ausente") // se vazio
);
// Saída: Olá Maria
or permite fornecer outro Optional caso o valor esteja vazio.
Optional<String> nome = Optional.empty();
String resultado = nome
.or(() -> Optional.of("Padrão"))
.get();
System.out.println(resultado); // Padrão
O método stream transforma o Optional em uma Stream com no máximo 1 elemento.
Optional<String> nome = Optional.of("Ana");
List<String> lista = nome.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(lista); // [ANA]
Se for um Optional de uma lista, o streamgera uma Stream com um único elemento: a lista inteira.
Optional<List<String>> optLista = Optional.of(List.of("A", "B", "C"));
optLista.stream()
.forEach(System.out::println);
// Saída [A, B, C]
melhoria no Try-with-resources
Agora você pode usar recursos declarados antes do try.
BufferedReader br = new BufferedReader(new FileReader("dados.txt"));
try (br) {
System.out.println(br.readLine());
}
Métodos privados em interfaces
Podemos extrair lógica comum dentro da própria interface.
interface Validador {
default boolean validar(String s) {
return s != null && comum(s);
}
private boolean comum(String s) {
return !s.isEmpty();
}
}
Java 10
O Java 10 nos trouxe o tipo var, que ajuda a aumentar a legibilidade dentro de blocos de código.
// Antes
for (Iterator<String> it = nomes.iterator(); it.hasNext();) {
String nome = it.next();
}
// Java 10
for (var it = nomes.iterator(); it.hasNext();) {
var nome = it.next();
}
O var não é tipagem dinâmica como em JavaScript. O tipo continua sendo estático, definido pelo compilador no momento da atribuição.
Ele não pode ser usado em:
- Atributos de classe
- Parametros de métodos
- Retorno de métodos A tipagem continua forte, apenas evita a repetição.
Para mim, os recursos do Java 9 que mais brilham para escrever código limpo são os novos métodos do Optional e os métodos para coleções imutáveis. São sem dúvida os que mais uso no meu dia a dia.
Confesso que ainda prefiro criar classes abstratas para implementar interfaces quando quero compartilhar lógica comum, porque me sinto mais seguro do que levar esse comportamento para uma interface que pode ser implementada em classes que não precisam dele.
Já os novos métodos da Streams API (como takeWhile e dropWhile) ainda não encontrei necessidade de usar em projetos reais — mas é bom saber que estão lá quando for preciso.
O var do Java 10 é um excelente recurso, e ainda estou aprendendo a aproveitá-lo melhor no dia a dia.
👉 Será que os métodos do Optional e o List.of também foram os que mais impactaram o seu dia a dia? Ou você acha que outro recurso merece mais destaque?
Clique aqui para ler a terceira parte.
Top comments (0)