在不包含所有项目的集合上引发错误

Raise an error on collection that does not contain all items

我想知道最干净的方法是用 RxJava 语法遍历集合并在任何项不存在时引发错误。下面显示了一个混合示例,但理想情况下我想要 RxJava 语法中的所有逻辑。:

public Single<List<Bar>> doSomething(Collection<String> ids) {
  Single<List<Bar>> bars = getAllBars();
  List<Bar> results = bars
  .flattenAsObservable(z-> z)
  .filter(bar -> ids.contains(bar.getId())
  .toList()
  .blockingGet();// Blocking since I don't know the RxJava syntax for below

  if (results.isEmpty()) {
    throw SomeError();
  }
  if (results.size() != ids.size()) {
    // Ideally know which bar(s) are not in the ids list
    throw someError();
  }
  return Single.just(results);
}

实际上,如果您在未找到 id 的情况下将错误传播到下游并在您想要对该错误采取行动的任何地方进行订阅,则可以非常简单地实现这一点。像这样包含有关缺失柱的信息也很容易:

public Single<List<Bar>> doSomething(Collection<String> ids) {
  return getAllBars()
    .map(bars -> {
      List<Bar> unknownBars = new ArrayList<>();
      for(Bar bar : bars) {
        if(!ids.contains(bar.getId()) {
          unknownBars.add(bar);
        }
      }
      if (unknownBars.isEmpty()) {
        return bars;
      } else {
        throw new BarsNotFoundException(unknownBars);
      }
    });
}

//elsewhere
doSomething(ids)
  .subscribe(bars -> { /* do something */ }, throwable -> { /* handle error */ });

如果在您的映射中到达 throw 语句,您的订阅方法的第二个 lambda 将执行您抛出的错误。

我从自己使用 rx 中学到的东西:当你开始对它越来越熟悉时,它开始感觉像一把花哨的新锤子,突然间一切看起来都像钉子。请记住,只有当它能让您的生活更轻松而不是更艰难时才使用它。

也许你也可以拥有类似的东西:

public static void main(String[] args) {
    Collection<String> ids = List.of("id4", "id2", "id1", "id3"); // same ids
    // Collection<String> ids = List.of("id4", "id2", "id1", "id5"); // different ids
    // Collection<String> ids = List.of("id4", "id2", "id1", "id3", "id5"); // different ids
    // Collection<String> ids = List.of("id4", "id2", "id1"); // different ids

    doSomething(ids)
            .subscribe(l -> System.out.println("received: " + toString((List<Bar>) l)),
                       err -> System.err.println(err.getMessage()));

    Flowable.timer(60, SECONDS) // Just to block the main thread for a while
            .blockingSubscribe();
}

private static Single<List<Bar>> doSomething(Collection<String> ids) {
    return getAllBars().flatMap(bars -> {
                           List<String> unknownBarIds = bars.stream().map(Bar::getId).collect(Collectors.toList());
                           unknownBarIds.removeAll(ids);
                           return unknownBarIds.isEmpty()
                                            ? Single.just(bars)
                                            : Single.error(new Exception("unknown bars: " + unknownBarIds));
                       })
                       .flatMap(bars -> {
                           List<String> barIds = bars.stream().map(Bar::getId).collect(Collectors.toList());
                           List<String> missingIds = new ArrayList<>(ids);
                           missingIds.removeAll(barIds);
                           return missingIds.isEmpty()
                                        ? Single.just(bars)
                                        : Single.error(new Exception("missing bars: " + missingIds));
                       });
}

private static Single<List<Bar>> getAllBars() {
    return Single.just(List.of(new Bar("id2"), new Bar("id1"), new Bar("id3"), new Bar("id4")));
}

private static String toString(final List<Bar> bars) {
    return bars.stream().map(Bar::getId).collect(Collectors.joining(", "));
}

如果您希望在接收流程中保留错误?