回答編集履歴

1

コード解説追加

2017/11/10 19:47

投稿

swordone
swordone

スコア20649

test CHANGED
@@ -5,6 +5,14 @@
5
5
 
6
6
 
7
7
  Comparator.comparingIntはComparator<T>を返す**staticメソッド**です。このメソッドを渡すと、このTの部分をElementであるとしてコンパイルしてくれるのです。このため、2はコンパイルが通ります。
8
+
9
+ ```java
10
+
11
+ // Comparator.comparingIntの総称型を自動でElementと推定
12
+
13
+ Collections.sort(list, Comparator.comparingInt(e -> e.n1));
14
+
15
+ ```
8
16
 
9
17
 
10
18
 
@@ -14,6 +22,54 @@
14
22
 
15
23
  つまり、comparingIntやthenComparingIntに渡しているラムダ式のeがObjectとして扱われ、Objectクラスにn1,n2,n3というフィールドがないため、ご質問のエラーが出ます。
16
24
 
25
+ ```java
26
+
27
+ // この段階では型推論が効かないため、comparingIntの総称型はObject扱い
28
+
29
+ // つまり、ラムダ式はToIntFunction<Object>で、eの型がObject扱い
30
+
31
+ Collections.sort(list, Comparator.comparingInt(e -> e.n1)
32
+
33
+ // これ以降はComparator<Object>に対してthencomparingIntを呼んでいるため、
34
+
35
+ // 引数ラムダ式はToIntFunction<Object>
36
+
37
+ .thenComparingInt(e -> e.n2)
38
+
39
+ .thenComparingInt(e -> e.n3));
40
+
41
+ ```
42
+
17
43
 
18
44
 
19
45
  この問題は、comparingIntにおけるTがElementとわかれば解決します。そのため、総称型を明示的に指定する(4の方法)か、ラムダ式の引数、つまりFunctionの型を明示する(5の方法)ことでコンパイルが通るようになるのです。
46
+
47
+ ```java
48
+
49
+ // comparingIntの総称型を明示的にElementにすることで、引数ラムダ式をToIntFunction<Element>と推定
50
+
51
+ Collections.sort(list, Comparator.<Element>comparingInt(e -> e.n1)
52
+
53
+ // 以降もComparator<Element>に対するメソッドのため、Elementに対する操作とわかる
54
+
55
+ .thenComparingInt(e -> e.n2)
56
+
57
+ .thenComparingInt(e -> e.n3));
58
+
59
+ ```
60
+
61
+ ```java
62
+
63
+ // ラムダ式の引数型をElementと明示することて、このラムダ式がToIntFunction<Element>に確定。
64
+
65
+ // これにより、comparingIntの総称型もElementに確定できる。
66
+
67
+ Collections.sort(list, Comparator.comparingInt((Element e) -> e.n1)
68
+
69
+ // 以下、先述通り
70
+
71
+ .thenComparingInt(e -> e.n2)
72
+
73
+ .thenComparingInt(e -> e.n3));
74
+
75
+ ```