title: Very confused by Java 8 Comparator type inference
body: <p>I've been looking at the difference between <code>Collections.sort</code> and <code>list.sort</code>, specifically regarding using the <code>Comparator</code> static methods and whether param types are required in the lambda expressions. Before we start, I know I could use method references, e.g. <code>Song::getTitle</code> to overcome my problems, but my query here is not so much something I want to fix but something I want an answer to, i.e. why is the Java compiler handling it in this way. </p>
  
  <p>These are my finding. Suppose we have an <code>ArrayList</code> of type <code>Song</code>, with some songs added, there are 3 standard get methods:</p>
  
  <pre><code>    ArrayList&lt;Song&gt; playlist1 = new ArrayList&lt;Song&gt;();
  
      //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") );
  </code></pre>
  
  <p>Here is a call to both types of sort method that works, no problem:</p>
  
  <pre><code>Collections.sort(playlist1, 
              Comparator.comparing(p1 -&gt; p1.getTitle()));
  
  playlist1.sort(
              Comparator.comparing(p1 -&gt; p1.getTitle()));
  </code></pre>
  
  <p>As soon as I start to chain <code>thenComparing</code>, the following happens:</p>
  
  <pre><code>Collections.sort(playlist1,
              Comparator.comparing(p1 -&gt; p1.getTitle())
              .thenComparing(p1 -&gt; p1.getDuration())
              .thenComparing(p1 -&gt; p1.getArtist())
              );
  
  playlist1.sort(
          Comparator.comparing(p1 -&gt; p1.getTitle())
          .thenComparing(p1 -&gt; p1.getDuration())
          .thenComparing(p1 -&gt; p1.getArtist())
          );
  </code></pre>
  
  <p>i.e. syntax errors because it does not know the type of <code>p1</code> anymore. So to fix this I add the type <code>Song</code> to the first parameter (of comparing):</p>
  
  <pre><code>Collections.sort(playlist1,
              Comparator.comparing((Song p1) -&gt; p1.getTitle())
              .thenComparing(p1 -&gt; p1.getDuration())
              .thenComparing(p1 -&gt; p1.getArtist())
              );
  
  playlist1.sort(
          Comparator.comparing((Song p1) -&gt; p1.getTitle())
          .thenComparing(p1 -&gt; p1.getDuration())
          .thenComparing(p1 -&gt; p1.getArtist())
          );
  </code></pre>
  
  <p>Now here comes the CONFUSING part. For p<code>laylist1.sort</code>, i.e. the List, this solve all compilation errors, for both the following <code>thenComparing</code> calls. However, for <code>Collections.sort</code>, it solves it for the first one, but not the last one. I tested added several extra calls to <code>thenComparing</code> and it always shows an error for the last one, unless I put <code>(Song p1)</code> for the parameter.</p>
  
  <p>Now I went on to test this further with creating a <code>TreeSet</code> and with using <code>Objects.compare</code>:</p>
  
  <pre><code>int x = Objects.compare(t1, t2, 
                  Comparator.comparing((Song p1) -&gt; p1.getTitle())
                  .thenComparing(p1 -&gt; p1.getDuration())
                  .thenComparing(p1 -&gt; p1.getArtist())
                  );
  
  
      Set&lt;Song&gt; set = new TreeSet&lt;Song&gt;(
              Comparator.comparing((Song p1) -&gt; p1.getTitle())
              .thenComparing(p1 -&gt; p1.getDuration())
              .thenComparing(p1 -&gt; p1.getArtist())
              );
  </code></pre>
  
  <p>The same thing happens as in, for the <code>TreeSet</code>, there are no compilation errors but for <code>Objects.compare</code> the last call to <code>thenComparing</code> shows an error.</p>
  
  <p>Can anyone please explain why this is happening and also why there is no need to use <code>(Song p1)</code> at all when simply calling the comparing method (without further <code>thenComparing</code> calls).</p>
  
  <p>One other query on the same topic is when I do this to the <code>TreeSet</code>:</p>
  
  <pre><code>Set&lt;Song&gt; set = new TreeSet&lt;Song&gt;(
              Comparator.comparing(p1 -&gt; p1.getTitle())
              .thenComparing(p1 -&gt; p1.getDuration())
              .thenComparing(p1 -&gt; p1.getArtist())
              );
  </code></pre>
  
  <p>i.e. remove the type <code>Song</code> from the first lambda parameter for the comparing method call, it shows syntax errors under the call to comparing and the first call to <code>thenComparing</code> but not to the final call to <code>thenComparing</code> - almost the opposite of what was happening above! Whereas, for all the other 3 examples i.e. with <code>Objects.compare</code>, <code>List.sort</code> and <code>Collections.sort</code> when I remove that first <code>Song</code> param type it shows syntax errors for all the calls.</p>
  
  <p>Many thanks in advance.</p>
  
  <p>Edited to include screenshot of errors I was receiving in Eclipse Kepler SR2, which I have now since found are Eclipse specific because when compiled using the JDK8 java compiler on the command-line it compiles OK. </p>
  
  <p><img src="https://i.stack.imgur.com/cPEfH.jpg" alt="Sort errors in Eclipse"></p>