O -> indica uma expressão lâmbda.
Você pode usar toda vez que o parâmetro for uma interface que só tenha um único método.
Imagina que você tem a seguinte interface:
public interface MinhaInterface {
public void unicoMetodoDaInterface(String parametro);
}
E a seguinte classe que tem um método que recebe um objeto da interface acima:
public class MinhaClasse {
public void meuMetodo(MinhaInterface objeto) {
objeto.unicoMetodoDaInterface("Hello World");
}
}
Antigamente, quando não havia expressões lambda, era comum utilizar classes anônimas, por exemplo:
public class ExemploSemLambda {
public static void main(String[] args) {
MinhaClasse objetoDaMinhaClasse = new MinhaClasse();
objetoDaMinhaClasse.meuMetodo(new MinhaInterface() {
@Override
public void unicoMetodoDaInterface(String parametro) {
System.out.println("Mensagem recebida: " + parametro);
}
});
}
}
Com expressões lambda o mesmo código pode ser reescrito para:
public class ExemploComLambda {
public static void main(String[] args) {
MinhaClasse objetoDaMinhaClasse = new MinhaClasse();
objetoDaMinhaClasse.meuMetodo(parametro -> System.out.println("Mensagem recebida: " + parametro));
}
}
Quando sua expressão é para executar mais de uma linha de código, você pode utilizar { } para definir o bloco de código, exemplo:
public void executar() {
MinhaClasse objetoDaMinhaClasse = new MinhaClasse();
objetoDaMinhaClasse.meuMetodo(parametro -> {
System.out.println("Primeira linha de codigo");
System.out.println("Segunda linha de codigo");
});
}
Mas nestes casos, acho mais legível definir outro método, dessa forma por exemplo::
public void executar() {
MinhaClasse objetoDaMinhaClasse = new MinhaClasse();
objetoDaMinhaClasse.meuMetodo(parametro -> outroMetodo(parametro));
}
private void outroMetodo(String parametro) {
System.out.println("Primeira linha de codigo");
System.out.println("Segunda linha de codigo");
System.out.println("Terceira linha de codigo");
System.out.println("Tantas linhas quantas você quiser");
}