Railsのアドベントカレンダーを見てたら、こんなエントリを発見。
眺めてたらなんとなく「Javaでも同じようにできるんじゃね?」って気になってきたので、書いとく。
リファクタリング 1st
true/falseで条件分岐
Before
List<Comment> comments;
public boolean hasComments() {
if(this.comments.size() > 0) {
return true;
} else {
return false;
}
}
Javaとか関係なく、これはワンライナーだよねー
After
List<Comment> comments;
public boolean hasComments() {
return this.comments.size() > 0;
}
- 追記
public boolean hasComments() {
return !this.comments.isEmpty();
}
のほうがいいんじゃない?というリクエストがありましたが、個人的にはnot演算子は見えにくいのと、ぱっと見の読みづらさがあって、好みではないです。好みの問題ですが・・・^^;
リファクタリング 2nd
commnetsが特定の条件を満たすかどうかの判定を書く場合。
Before
private List<Comment> comments;
private int user_id;
public boolean onlyMyComments() {
for(Comment comment : this.comments) {
if(comment.getUserId() != this.user_id) {
return false;
}
}
return true;
}
全てが条件を満たすか?の判定はStreamAPIのallMatchを使いましょう。これもワンライナーで。
After
private List<Comment> comments;
private int user_id;
public boolean onlyMyComments() {
return this.comments.stream().allMatch(commnet -> commnet.getUserId() == this.user_id);
}
リファクタリング 3rd
値の存在によって処理を変えるパターン
String value = "hoge";
...
if(value == null) {
System.out.println("null!!");
} else {
System.out.println(value);
}
値の存在によって処理を分けるにはOptionalを使いましょう。これもワンライナー。
After
Optional<String> value = Optional.of("hoge"); //空にするにはOptional.empty()
...
System.out.println(value.orElse("null!!"));
リファクタリング 4th
ループで回して、その合計を取るパターン。
Before
private List<Student> students;
public int total() {
int result = 0;
for(Student student : students) {
result += student.getScore();
}
return result;
}
Java8以降では「forを見たらstreamと思え!」という言葉がある(?)ように、streamを使えば美しく書けます。
After
private List<Student> students;
public int total() {
return students.stream().mapToInt(student -> student.getScore()).sum();
}
途中のmapToIntでIntStreamに変換するのがポイント。硬派にmapとreduceでやりたい人は
private List<Student> students;
public int total() {
return students.stream().map(student -> student.getScore()).reduce(0, (value1, value2) -> value1 + value2);
}
まとめ
Java8以降ではStream APIをガリガリ使えるかどうかが効率の良い、かつ、美しいコードを書くために必須になりますね。皆さんもJavaの美しいワンライナーを見つけてください!