Muito confuso com a inferência do tipo Java 8 Comparator
Eu estive olhando para a diferença entreCollections.sort
elist.sort
, especificamente sobre o uso doComparator
métodos estáticos e se os tipos de parâmetros são necessários nas expressões lambda. Antes de começarmos, sei que poderia usar referências de métodos, por exemploSong::getTitle
para superar meus problemas, mas minha consulta aqui não é tanto algo que eu quero corrigir, mas algo que eu quero uma resposta, ou seja, por que o compilador Java está lidando com isso dessa maneira.
Estes são os meus achados. Suponha que tenhamos umArrayList
do tipoSong
, com algumas músicas adicionadas, existem três métodos padrão de obtenção:
ArrayList<Song> playlist1 = new ArrayList<Song>();
//add some new Song objects
playlist.addSong( new Song("Only Girl (In The World)", 235, "Rhianna") );
playlist.addSong( new Song("Thinking of Me", 206, "Olly Murs") );
playlist.addSong( new Song("Raise Your Glass", 202,"P!nk") );
Aqui está uma chamada para os dois tipos de método de classificação que funcionam, não há problema:
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle()));
playlist1.sort(
Comparator.comparing(p1 -> p1.getTitle()));
Assim que eu começar a encadearthenComparing
, acontece o seguinte:
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
playlist1.sort(
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
ou seja, erros de sintaxe porque não sabe o tipo dep1
não mais. Então, para corrigir isso, eu adiciono o tipoSong
para o primeiro parâmetro (de comparação):
Collections.sort(playlist1,
Comparator.comparing((Song p1) -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
playlist1.sort(
Comparator.comparing((Song p1) -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
Agora, aqui vem a parte confusa. Para playlist1.sort
, ou seja, a Lista, isso resolve todos os erros de compilação, para os seguintesthenComparing
chamadas. No entanto, paraCollections.sort
, resolve o primeiro, mas não o último. Eu testei adicionei várias chamadas extras parathenComparing
e sempre mostra um erro para o último, a menos que eu coloque(Song p1)
para o parâmetro
Agora, testei isso ainda mais criando umTreeSet
e com o usoObjects.compare
:
int x = Objects.compare(t1, t2,
Comparator.comparing((Song p1) -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
Set<Song> set = new TreeSet<Song>(
Comparator.comparing((Song p1) -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
O mesmo acontece como em, para oTreeSet
, não há erros de compilação, mas paraObjects.compare
a última chamada parathenComparing
mostra um erro.
Alguém pode explicar por que isso está acontecendo e também por que não há necessidade de usar(Song p1)
quando simplesmente chamamos o método de comparação (sem maisthenComparing
chamadas).
Uma outra consulta sobre o mesmo tópico é quando eu faço isso com oTreeSet
:
Set<Song> set = new TreeSet<Song>(
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
ou seja, remova o tipoSong
do primeiro parâmetro lambda para a chamada do método de comparação, ele mostra erros de sintaxe na chamada de comparação e na primeira chamada parathenComparing
mas não para a chamada final parathenComparing
- quase o oposto do que estava acontecendo acima! Considerando que, para todos os outros 3 exemplos, ou seja, comObjects.compare
, List.sort
eCollections.sort
quando eu removo isso primeiroSong
tipo param mostra erros de sintaxe para todas as chamadas.
Muito obrigado antecipadamente.
Editado para incluir a captura de tela dos erros que eu estava recebendo no Eclipse Kepler SR2, que encontrei desde então, são específicos do Eclipse porque, quando compilados usando o compilador JDK8 java na linha de comando, ele compila OK.