#java #android #rx-java
#java #Android #rx-java
Вопрос:
Наличие двух потоков, подобных следующему
Stream 1: A -- B -- C -- D
Stream 2: 3 -- 1 -- 2 -- 4
Я хотел бы вывести
Output: A1 -- B2 -- C3 -- D4
или
Output: 3C -- 2B -- 1A -- 4D
Где каждая буква сопоставляется с ее положением в алфавите.
Я пробовал использовать операторы .zip
и .combineLatest
, но не получил нужного результата.
На самом деле это упрощение моей проблемы, на самом деле. A, B и C — это объекты, которые имеют свойства типа 1,2 или 3. Итак, я могу сделать что-то вроде A.position() = 1
Есть ли оператор, который конкретно решает мою проблему, или мне придется использовать хэш-карту и сопоставлять эти объекты самостоятельно?
Заранее спасибо.
Комментарии:
1. что такое операторы .zip и .cimbineLatest?
2. они являются реактивными операторами reactivex.io
3. Спасибо за простую абстракцию вашей проблемы в вопросе, это вносит приятные изменения! Интересная проблема, кстати, особенно для обработки бесконечных потоков и хорошей обработки противодавления (возможно, не ваш вариант использования, но все равно интересно).
4. В вашем втором варианте вывода
1A
должно быть перед2B
Ответ №1:
Используйте Observable.toSortedList
, как показано ниже:
Observable<Data> s1 = Observable.from(new Data[]{new Data(3), new Data(1), new Data(2), new Data(4)});
Observable<String> s2 = Observable.from(new String[]{"A", "B", "C", "D"});
Observable.zip(
s1.toSortedList(this::compare).flatMap(Observable::from),
s2,
(d, s) -> s d.number
).subscribe(s -> {
//Output: A1 -- B2 -- C3 -- D4
});
compare
способ:
private Integer compare(Data a, Data b) {
return a.number.equals(b.number) ? 0 : (a.number < b.number ? -1 : 1);
}
Data
класс:
class Data {
private final Integer number;
Data(Integer number) {
this.number = number;
}
}
Комментарии:
1. Возможно, я выбрал плохой пример в своем ответе, но «toSortedList» не сработал бы для моей версии, поток s1 содержит объекты с идентификаторами, а не числами. Я перепишу свой ответ, чтобы сделать его более общим.
Ответ №2:
я бы попробовал что-то вроде .flatMap() в одном потоке с .groupBy (ключ) в другом потоке, который будет выдавать Observable<GroupedObservable<YourType>>
или иным образом используйте .toMap() или .toMultimap() в другом потоке, который создаст наблюдаемые<Map<K,Collection<T>>>
не уверен, ожидаете ли вы определенного порядка
Ответ №3:
Вы можете использовать модульно протестированный оператор match из rxjava-extras 0.8.0.3 (или более поздней версии, если она доступна). Артефакт опубликован на Maven Central.
Добавьте это в свой pom.xml:
<dependency>
<groupId>com.github.davidmoten</groupId>
<artifactId>rxjava-extras</artifactId>
<version>0.8.0.3</version>
</dependency>
Пример:
Observable<Integer> a = Observable.just(1, 2, 4, 3);
Observable<Integer> b = Observable.just(1, 2, 3, 5, 6, 4);
Obs.match(a, b,
x -> x, // key to match on for a
x -> x, // key to match on for b
(x, y) -> x // combiner
)
.forEach(System.out::println);
Вывод:
1
2
4
3
Комментарии:
1. Пожалуйста, обратите внимание, что я просто завершаю модульное тестирование оператора
match
в rxjava-extras. Приведенный выше алгоритм не обрабатывает повторы должным образом. Я дам вам знать, когда буду готов, выйдет в ближайшие пару дней.2. заменил мой ответ недавно написанным оператором. Дайте мне знать, если возникнут какие-либо проблемы (предпочтительно как проблема в rxjava-extras на github).