くわっちょさんのレガシーコードを見て思うこ と #jjug Title くわっちょさんのレガシーコードを見て思うこと #jjug Category Programming::Java::StreamAPI Created at 2014-08-23T11:24:32.000+09:00 Created by making Updated at 2014-08-23T11:24:32.000+09:00 Updated by making Orininal URL http://blog.ik.am/#/entries/279 昨日のJJUGナイトセミナーのLT大会でくわっちょさんのLTをみて、う∼んと思った。 Before Jjug ナイト・セミナー くわっちょ 20140822 from くわっ ちょ After Jjug ナイト・セミナー くわっちょ 20140822 from くわっ ちょ なんというかfor文とかif文とか見た目的な部分がレガシーなのではなく、 複数のことをごっちゃまぜにして処理をしているのがレガシーなんじゃ ないかなーと。 そこが治っていないとStream APIを使っても改善された感じが全くしない。(むしろ見にくくなってStream APIがdisられるだけなような) if分が多 いとかfor文が古いとかそういう問題じゃない。 処理を分解すると、何らかのルールに基づいて数値を変換する部分と、その数値を用いて文字列を作成する部分に分けられる。 Stream APIを使 うと分けた部分を以下のようにつなげることができる。 public static void main(String[] args) { List<Integer> list = Arrays.asList(31, 12, 23, 74, 65); list.stream() .mapToInt(Integer::intValue) .map(i -> { if (i < 5) { return 5; } else if (i < 11) { return 11; } else if (i < 16) { return 16; } else if (i < 21) { return 21; } else if (i < 26) { return 26; } else if (i < 31) { return 31; } else if (i < 41) { return 41; } else if (i < 51) { return 51; } else { return i; } }) .mapToObj(i -> { if (i > 51) { return "greater than 51"; } else { return "less than " + i; } }) .forEach(System.out::println); } 前半でintを変換して、後半でそのintを出力用のStringに変換した。三項演算子は複数回使うと見にくくなるので、if文に変えた。 前半部分は長い ので、以下のように別関数にわけても良いと思う。 public static void main(String[] args) { List<Integer> list = Arrays.asList(31, 12, 23, 74, 65); list.stream() .mapToInt(Integer::intValue) .map(Hoge::convert) .mapToObj(i -> { if (i > 51) { return "greater than 51"; } else { return "less than " + i; } }) .forEach(System.out::println); } static int convert(int i) { if (i < 5) { return 5; } else if (i < 11) { return 11; } else if (i < 16) { return 16; } else if (i < 21) { return 21; } else if (i < 26) { return 26; } else if (i < 31) { return 31; } else if (i < 41) { return 41; } else if (i < 51) { return 51; } else { return i; } } 分けておくと、convertの結果をmemo化することもできる。 まあ、これでも見やすいような気はするけど、if文が気になるなら、convertを少し工夫することになる。 やりたいことをよく見ると、"「5, 11, 16, 21, 26, 31, 41, 51」のうち、xより大きい最小の整数を求める"ことに置き換えられるので、これを実装 すると、 public static void main(String[] args) { List<Integer> list = Arrays.asList(31, 12, 23, 74, 65); list.stream() .mapToInt(Integer::intValue) .map(Hoge::convert) .mapToObj(i -> { if (i > 51) { return "greater than 51"; } else { return "less than " + i; } }) .forEach(System.out::println); } static int convert(int i) { return IntStream.of(5, 11, 16, 21, 26, 31, 41, 51) .filter(x -> i < x) .findFirst() .orElse(i); } と書ける。 ワンライナーが好きなら、 public static void main(String[] args) { List<Integer> list = Arrays.asList(31, 12, 23, 74, 65); list.stream() .mapToInt(Integer::intValue) .map(i -> IntStream.of(5, 11, 16, 21, 26, 31, 41, 51) .filter(x -> i < x) .findFirst() .orElse(i)) .mapToObj(i -> { if (i > 51) { return "greater than 51"; } else { return "less than " + i; } }) .forEach(System.out::println); } こんな感じかな∼
© Copyright 2024 ExpyDoc