LoginSignup
4
5

More than 5 years have passed since last update.

RxJava でズンドコキヨシ(window or buffer 使用)

Last updated at Posted at 2016-03-12

調子に乗って RxJava でもやってみた。
がんばって Observable.window を使ってみた。

zondoko.java

// なんちゃってラムダ使用。あと Android。
public void doZondoko() {
    final Random random = new Random();
    final List<String> PATTERN = Arrays.asList("ずん", "ずん", "ずん", "ずん", "どこ");
    final String K = "キ・ヨ・シ!";

    Observable.concat( // ※ の Observable<List<String>> を直列に連結
        Observable.interval(500, TimeUnit.MILLISECONDS)
            .map(_ -> random.nextInt(2) == 0 ? "ずん" : "どこ") // ランダムに ずん or どこ
            .window(PATTERN.size(), 1) // 要素数5のWindowを1ずつズラしてく
            .map(window -> window.toList())) // Observable<Observable<String>> を Observable<List<String>> に変換 ※
        .flatMap(window -> {
            if (sequenceEqual(window, PATTERN)) { // パターンと一致していたら…
                final List<String> says = new ArrayList<>();
                says.addAll(window);
                says.add(K);                      // キ・ヨ・シ!を追加
                return Observable.concat(
                        Observable.just(says),
                        Observable.just(Collections.<String>emptyList())); // 終了判定用の空リスト
            } else {
                return Observable.just(window);
            }
        })
        .takeWhile(says -> !says.isEmpty())  // 空リストになるまで繰り返す
        .subscribe(says -> Log.d(TAG, dump(says)));
}

/** リストとリストの要素一致 */
private boolean sequenceEqual(List<String> listA, List<String> listB) {
    Iterator<String> iterA = listA.iterator();
    Iterator<String> iterB = listB.iterator();

    while (iterA.hasNext() && iterB.hasNext()) {
        if (iterA.next() != iterB.next()) {
            return false;
        }
    }
    return (!iterA.hasNext() && !iterB.hasNext());
}

/** リスト内容をダンプ */
private String dump(List<String> list) {
    final StringBuilder b = new StringBuilder();
    for (String s : list) {
        if (!TextUtils.isEmpty(b.toString())) {
            b.append(", ");
        }
        b.append(s);
    }

    return b.toString();
}

どこ, ずん, どこ, どこ, ずん
ずん, どこ, どこ, ずん, どこ
どこ, どこ, ずん, どこ, ずん
どこ, ずん, どこ, ずん, どこ
ずん, どこ, ずん, どこ, どこ
どこ, ずん, どこ, どこ, ずん
ずん, どこ, どこ, ずん, ずん
どこ, どこ, ずん, ずん, ずん
どこ, ずん, ずん, ずん, ずん
ずん, ずん, ずん, ずん, どこ, キ・ヨ・シ!

「window(5, 1) -> toList -> concat してるならそれは buffer(5, 1) やんけ」というのを こちら で知って、 buffer 版も書いてみた。

Zondoko_buffer.java
public void doZondoko() {
    final Random random = new Random();
    final List<String> PATTERN = Arrays.asList("ずん", "ずん", "ずん", "ずん", "どこ");
    final String K = "キ・ヨ・シ!";

    Observable.interval(500, TimeUnit.MILLISECONDS)
        .map(_ -> random.nextInt(2) == 0 ? "ずん" : "どこ") // ランダムに ずん or どこ
        .buffer(PATTERN.size(), 1) // 要素数5のBufferを1ずつズラしてく
        .flatMap(buf -> {
            if (sequenceEqual(buf, PATTERN)) { // パターンと一致していたら…
                final List<String> says = new ArrayList<>();
                says.addAll(buf);
                says.add(K);                      // キ・ヨ・シ!を追加
                return Observable.concat(
                        Observable.just(says),
                        Observable.just(Collections.<String>emptyList())); // 終了判定用の空リスト
            } else {
                return Observable.just(buf);
            }
        })
        .takeWhile(says -> !says.isEmpty())  // 空リストになるまで繰り返す
        .subscribe(says -> Log.d(TAG, dump(says)));
}
4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5