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.

questionAnswers(4)

yourAnswerToTheQuestion