rxjava过滤器,用于流中的项目与流中的任何其他过滤器不匹配

时间:2019-12-03 21:22:13

标签: rx-java

我的应用程序中的CommandManager通过网络协议接收命令,并将其发布在PublishSubject命令上。特定的CommandHandler类订阅命令PublishSubject,以便每个CommandHandler仅接收设计用来处理的命令。我还希望有一个Default命令处理程序,该处理程序只接收那些其他CommandHandler的过滤谓词没有匹配的命令。

// Each CommandHandler subscribes to a filtered 
// stream of incoming commands matching this CommanHandler

commandManager.getCommandsPublishSubject()
.filter(getMessageFilterPredicate())
.subscribe(this::onNewMessage, 
     e -> LOGGER.error("Error getting new message", e));

有没有一种方法可以应用与任何CommandHandler不匹配的项目匹配的过滤器?

1 个答案:

答案 0 :(得分:1)

没有标准的运算符可以执行此操作。您必须创建一个自定义组件,而不是运算符,以承载过滤器lambda和每种情况下的更多主题以及默认主题。

public final class FilteringDispatcher<T> {

    static final class FilterAndSubject<T> {
         Predicate<T> predicate;
         Subject<T> subject;
    }

    final ConcurrentMap<String, FilterAndSubject<T>> filters = new ConcurrentHashMap<>();

    final Subject<T> defaultSubject = PublishSubject.<T>create().toSerialized();

    public Observable<T> registerPredicate(String name, Predicate<T> predicate) {
         Subject<T> subject = PublishSubject.<T>create().toSerialized();
         FilterAndSubject fs = new FilterAndSubject();
         fs.predicate = predicate;
         fs.subject = subject;

         FilterAndSubject old = filters.putIfAbsent(name, fs);
         return old != null ? old.subject : subject;
    }

    public Observable<T> getObservable(String name) {
        return filters.get(name).subject;
    }

    public Observable<T> getDefaultObservable() {
        return defaultSubject;
    }

    public void onNext(T item) {
        for (FilterAndSubject fs : filters.values()) {
            if (fs.predicate.test(item)) {
                fs.subject.onNext(item);
                return;
            }
        }
        defaultSubject.onNext(item);
    }
}
相关问题