HackerQuest

No app, no life

趣味と実益を兼ねてプログラマをやっている者👨‍💻

ラムダ式よりメソッド参照 Javaのお話

はじめに

最近Javaの勉強し始めました
勉強をする前は、あまりJavaを好きではなかったのですが、勉強しているうちに愛着が沸いて結構お気に入りになってきています。笑
そこでふと疑問に思ったことを今回はだらだらと書いてみたいと思います。

f:id:tsudukihashi0817:20190420123338j:plain 出典: https://duke.kenai.com/SunRIP/.Midsize/SunRIP.png.png

疑問

Java8以降から存在しているラムダ式とメソッド参照どちらがよりスマートなのか?

準備

簡単なソートを行います。
まずID番号と名前を持ったメンバークラスを用意します。

public class Member {
    private  int id;
    private String name;

    public Member(int id, String name){
        this.id = id;
        this.name = name;
    }

    public Member(){
        this(0,"名無し");
    }

    public int getId(){
        return this.id;
    }

    public void setId(int id){
        this.id = id;
    }

    public String getName(){
        return this.name;
    }

    public void setName(String name){
        this.name = name;
    }

    @Override
    public String toString(){
        return "ID: " + this.id + "\t名前: " + this.name;
    }
}

次にMainクラスを用意します。

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Member member= new Member();

        List<Member> list = new ArrayList<>();
        list.add(new Member(3,"田中太郎"));
        list.add(new Member(19,"山田太郎"));
        list.add(new Member(1,"鈴木一郎"));

        for(Member m : list){
            System.out.println(m);
        }
    }
}

実行結果:

ID: 3   名前: 田中太郎
ID: 19  名前: 山田太郎
ID: 1   名前: 鈴木一郎

ソートしてみよう

これを昇順にソートする方法を調べてみると以下のようなものが出てきました。

list.sort((o1, o2) -> o1.getId() - o2.getId());

出力結果:

ID: 1   名前: 鈴木一郎
ID: 3   名前: 田中太郎
ID: 19  名前: 山田太郎

?!?!?!!?!?!!?!

って感じでした。

これは以下の処理をlistに対して行なっているそうです。

  • Comparatorインターフェースのcompare()が省略
  • o1.getId() - o2.getId() が正ならsort()によりo1が前に来る
  • 負ならsort()によりo1が前に来る
  • 0なら移動しない

すごくスマートな書き方ですが、分かり難かったです、、、
自分がスマートではないので、もっと優しい解決方法を探しました!

メソッド参照

list.sort(Comparator.comparing(Member::getId));

(※import java.util.Comparator;が必要)

さっきよりはわかりやすい!

逆順

逆順にするのも簡単!

list.sort(Comparator.comparing(Member::getId).reversed());

import static java.util.Comparator.*; をすることによってコードも短くできました。

list.sort(comparing(Member::getId).reversed());

Null処理

Null処理も簡単!
import static java.util.Comparator.*; を忘れずに行なってください。

Null処理を見せるためメンバー変数のint型を全てIntegerに変更
Autoboxing最高

public class Member {
    private  Integer id;
    private String name;

    public Member(Integer id, String name){
        this.id = id;
        this.name = name;
    }

    public Member(){
        this(0,"名無し");
    }

    public Integer getId(){
        return this.id;
    }

Mainクラス

import java.util.ArrayList;
import static java.util.Comparator.*;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Member member= new Member();

        List<Member> list = new ArrayList<>();
        list.add(new Member(3,"田中太郎"));
        list.add(new Member(19,"山田太郎"));
        list.add(new Member(null,"摩利男"));
        list.add(new Member(1,"鈴木一郎"));

        list.sort(comparing(Member::getId,nullsLast(naturalOrder())));

        for(Member m : list){
            System.out.println(m);
        }
    }
}

出力結果:

ID: 1   名前: 鈴木一郎
ID: 3   名前: 田中太郎
ID: 19  名前: 山田太郎
ID: null    名前: 摩利男

まとめ

  • ラムダ式はカッコイイけど、個人的にはわかりづらい
  • メソッド参照は記述は増えるけど、わかりやすく使いやすい

多分、規約がなければ自分はメソッド参照を使用していくと思います。

以上駄文にお付き合いいただきありがとうございました。

参考文献

qiita.com

www.ne.jp

Ryo Tsuzukihashi