特に静的メソッドの使用と、ラムダ式でparamタイプが必要かどうかに関して、Collections.sort
との違いを調べてきました。始める前に、たとえば問題を克服するためにメソッド参照を使用できることはわかっていますが、ここでのクエリは修正したいものではなく、答えが必要なものです。つまり、Javaコンパイラがこのように処理するのはなぜですか。 。list.sort
Comparator
Song::getTitle
これらは私の発見です。我々が持っていると仮定しArrayList
たタイプのをSong
追加いくつかの曲で、3つの標準getメソッドがあります:
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") );
これは、機能する両方のタイプのソートメソッドの呼び出しです。問題ありません。
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle()));
playlist1.sort(
Comparator.comparing(p1 -> p1.getTitle()));
チェーンを開始するとすぐthenComparing
に、次のことが起こります。
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())
);
つまり、タイプがわからないため、構文エラーが発生しp1
ます。したがって、これを修正するSong
ために、(比較の)最初のパラメーターにタイプを追加します。
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())
);
ここで、紛らわしい部分があります。p laylist1.sort
、つまりリストの場合、これにより、次の両方のthenComparing
呼び出しのすべてのコンパイルエラーが解決されます。ただし、の場合Collections.sort
、最初の問題は解決されますが、最後の問題は解決されません。にいくつかの追加の呼び出しを追加してテストしましたが、パラメーターを指定しthenComparing
ない限り、最後の呼び出しでは常にエラーが表示され(Song p1)
ます。
次に、を作成しTreeSet
て使用して、これをさらにテストしましたObjects.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())
);
と同じことが起こります。のTreeSet
場合、コンパイルエラーはありませんがObjects.compare
、最後の呼び出しでエラーがthenComparing
表示されます。
なぜこれが起こっているのか、そして(Song p1)
単に比較メソッドを呼び出すときに(それ以上のthenComparing
呼び出しなしで)使用する必要がまったくない理由を誰かが説明できますか?
同じトピックに関するもう1つのクエリは、これを次のように実行する場合ですTreeSet
。
Set<Song> set = new TreeSet<Song>(
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
つまりSong
、compareingメソッド呼び出しの最初のラムダパラメーターから型を削除すると、comparingの呼び出しとtoの最初の呼び出しで構文エラーが表示されますがthenComparing
、最後の呼び出しでは表示されませんthenComparing
-上記で起こったこととほぼ逆です!他のすべての3例がでIE用、一方Objects.compare
、List.sort
そしてCollections.sort
私はその最初の削除するときSong
のparamタイプを、それはすべてのコールのための構文エラーを示しています。
よろしくお願いします。
Eclipse Kepler SR2で受け取ったエラーのスクリーンショットを含めるように編集しました。これは、コマンドラインでJDK8 Javaコンパイラーを使用してコンパイルすると、正常にコンパイルされるため、Eclipse固有のものであることがわかりました。