Java
FizzBuzz
java8
StreamAPI

[Java]プログラミングクイズSET INTERSECTIONをStreamAPIで一行で書いてみる

職場でプログラミングクイズをやった結果、二人が同じ答えになったのでメモ

SET INTERSECTIONとは

FizzBuzzのようなプログラミングクイズ。
今回はCodeEvalに載っていた問題にチャレンジします。

CodeEval - https://www.codeeval.com/browse/30/

問題(意訳)

2種類の(昇順に)ソートされた数字のリストを入力値とします。
リストは;で区切られ、リスト内の数字は,で区切られています。
2種類のリストで重複する数字を,区切りで出力します。

入力値サンプル
1,2,3,4;4,5,6

20,21,22;45,46,47

7,8,9;8,9,10,11,12
出力値サンプル
4

(何も出力しない)

8,9

※今回はJavaでやったので、args[0]に入力値サンプルが一行入るものとします。

こんなイメージ
java SetIntersection "1,2,3,4;4,5,6"

解答:一行で書いてみた(おふざけ)

色んな意味でone-linerになってしまいました。
(モジュール化、例外処理とかは一切考慮していない)

import java.util.Arrays;
import java.util.stream.Collectors;

public class SetIntersection {
  public static void main(String[] args) {

    System.out.println(String.join(",",
        Arrays.stream(args[0].split(";")[0].split(","))
            .filter(leftString -> Arrays.stream(args[0].split(";")[1].split(",")).anyMatch(leftString::equals))
            .collect(Collectors.toList())));

  }
}

解答:読みやすいように分解

filteranyMatchの条件に該当したものだけに絞り、リスト化します。
あとはString.joinでカンマ区切りで出力するというもの

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class SetIntersection {

  private static final String SEPARATOR_LIST = ";";
  private static final String SEPARATOR_NUMBER = ",";

  public static void main(String[] args) {

    Stream<String> leftSide = Arrays.stream(args[0].split(SEPARATOR_LIST)[0].split(SEPARATOR_NUMBER));
    List<String> rightSide = Arrays.asList(args[0].split(SEPARATOR_LIST)[1].split(SEPARATOR_NUMBER));

    System.out.println(String.join(SEPARATOR_NUMBER,
                                   leftSide.filter(leftString -> rightSide.stream().anyMatch(leftString::equals))
                                           .collect(Collectors.toList())));

  }
}

なお、解答はforとifを使うやり方と、streamでのやり方に二分されました。
言うまでもなく前者のほうが実行速度が早いですというオチ。