NPE while 过滤器列表 io.reactivex.Observable

NPE while filter list with io.reactivex.Observable

我在尝试将 StringArrayList 过滤为 Observable 时遇到问题。

如果满足以下条件,一切正常:

MatrixCursor suggestionsCursor =
        new MatrixCursor(new String[]{BaseColumns._ID, COLUMN_FIELD_NO});

for (int i = 0; i < data.size(); i++) {
    if (data.get(i) != null)
        if (data.get(i).toLowerCase().contains(newText.toLowerCase()))
            filtered.add(data.get(i));
}

int key = 0;
for (String suggestion : filtered) {
    suggestionsCursor.addRow(new Object[]{key++, suggestion});
}

但如果

MatrixCursor suggestionsCursor =
        new MatrixCursor(new String[]{BaseColumns._ID, COLUMN_FIELD_NO});

Observable.fromIterable(data)
        .filter(it->it!=null && it.toLowerCase().contains(newText.toLowerCase()))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .toList()
        .subscribe(strings -> {
            int key = 0;
            for (String suggestion : strings) {
                suggestionsCursor.addRow(new Object[]{key++, suggestion});
            }          
        });

因为我得到一个错误

io.reactivex.exceptions.OnErrorNotImplementedException: The iterator returned a null value

我哪里错了?

如评论中所述,不支持可迭代序列中的 null 值。此检查在 ObservableFromIterable.java class:

中强制执行
v = ObjectHelper.requireNonNull(it.next(), "The iterator returned a null value");

这也意味着像这样的过滤器没有帮助

.filter(it -> it != null)

无论如何,一个好的经验法则是处理错误异常

Observable.fromIterable(data)
        .filter(it->it!=null && it.toLowerCase().contains(newText.toLowerCase()))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .toList()
        .subscribe(strings -> {
            int key = 0;
            for (String suggestion : strings) {
                suggestionsCursor.addRow(new Object[]{key++, suggestion});
            }          
        }, error -> {
           /* handle exceptions here */
        });

您可以使用 Iterable Extensions 库 (IxJava) 进行预处理,这样您就可以使用 nulls:

Observable.fromIterable(
        Ix.from(data)
        .filter(it -> it != null 
             && it.toLowerCase().contains(newText.toLowerCase())
        )
    )
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .toList()
    .subscribe(strings -> {
        int key = 0;
        for (String suggestion : strings) {
            suggestionsCursor.addRow(new Object[]{key++, suggestion});
        }          
    }, 
    Throwable::printStackTrace);

两个答案都很好,但我找到了更简单的解决方案。

data.removeAll(Collections.singleton(null));

Strings

填充数据后