メソッド参照 ::
同じ名前を 2 回書いている
ラムダ式で短く書けるようになったはずなのに、まだ気になる形が残ります。
Java
lines.forEach(line -> System.out.println(line));このラムダ式がやっているのは、受け取った line を、そのまま println に渡すことだけです。line という名前は、受け取るために 1 回、渡すためにもう 1 回、合計 2 回書いています。中身を加工しているならともかく、素通しさせるためだけに名前を用意しているわけです。
この形は、名前ごと省けます。
Java
lines.forEach(System.out::println);:: の左に呼ぶ相手、右にメソッド名を書きます。引数は書きません。「流れてきたものを、このメソッドにそのまま渡す」という意味が、これだけで伝わります。これがメソッド参照です。
呼ぶ相手の書き方は 3 通り
:: の左に何を書くかは、どのメソッドを呼びたいかで決まります。
すでにあるオブジェクトのメソッドを呼ぶなら、そのオブジェクトを書きます。System.out::println がこの形で、System.out という決まった 1 つの出力先に対して println を呼びます。
static メソッドなら、クラス名を書きます。
Java
List<Integer> nums = texts.stream()
.map(s -> Integer.parseInt(s)) // ラムダ式
.toList();
List<Integer> nums = texts.stream()
.map(Integer::parseInt) // メソッド参照
.toList();3 つ目が少し変わっていて、流れてくる要素自身のメソッドを呼びたいときも、クラス名を書きます。
Java
List<String> cleaned = lines.stream()
.map(String::trim)
.toList();String::trim は「String クラスの trim を、流れてきたその String に対して呼ぶ」という意味です。static メソッド参照と見た目が同じなので混乱しやすいところですが、trim() は引数を取らないメソッドなので、Integer.parseInt(s) のように引数として渡すことはできません。どちらの意味になるかは、そのメソッドが static かどうかで自動的に決まります。
手を加えているなら、:: にはできない
メソッド参照にできるのは、受け取ったものを丸ごとそのメソッドに渡すときだけです。ほんの少しでも加工していたら使えません。
Java
.map(s -> s.trim() + "!") // 結果に足しているので不可
.filter(s -> s.length() > 3) // 呼んだ結果を比べているので不可どちらも「呼ぶだけ」を超えています。無理に短くしようとせず、ラムダ式のままにします。
短く書けるかどうかで迷ったら、そのラムダ式を声に出して読んでみてください。「受け取って、そのまま渡す」で言い切れるなら
::にできます。「受け取って、渡して、それから」と続くならできません。
やってみよう
Solution.toUpperJoined(String... arr) を完成させて、受け取った文字列を全部大文字にしてから , でつないだ結果を返してください。
Arrays.stream(arr) で Stream<String> を作り、map で大文字に変えて、Collectors.joining(",") でつなぎます。大文字にするメソッドは引数を取らないので、ラムダ式で書くと引数名がちょうど 2 回出てきます。そこが :: に置き換えられる形です。
引数が 1 つも無いときは空文字列が返ります。空文字列が要素として混ざっている ["a", "", "b"] のときは、大文字にしても空文字列のままなので、A,,B のように区切りが 2 つ続きます。
要件
Arrays.stream(arr)で配列からStream<String>を作ることmapにString::toUpperCaseの メソッド参照 を渡して大文字化すること (ラムダs -> s.toUpperCase()でも可だが、メソッド参照が望ましい)Collectors.joining(",")を使って,区切りで連結した結果を返すこと
入出力例
toUpperJoined("abc", "def") → "ABC,DEF"
toUpperJoined() → ""
toUpperJoined("hello") → "HELLO"
toUpperJoined("Java", "Stream", "Lambda") → "JAVA,STREAM,LAMBDA"
toUpperJoined("a", "", "b") → "A,,B"