我需要基于副作用映射RxJava发射。
每个排放项都将使用以下公式进行映射:
f(x) = const * x + counter
当const是偶数时,counter是0
;当const是奇数时,counter是-1
。
每次发射时,计数器都会递增。
常量和发射量都是整数,将从远程资源中获取。
将计数器放置为类属性确实可以解决该问题。但是这样的副作用将使它无法线程安全,并且在重置计数器之前不能被多次调用。
private var counter = 0
fun process(constSource: Single<Int>, entrySource: Flowable<Long>): Flowable<Long> {
fun mapper(const: Int, entry: Long) = Single.fromCallable {
if (const % 2 != 0) counter = -1
const * entry + counter++
}
return entrySource
.withLatestFrom(
constSource.toFlowable(),
BiFunction { entry: Long, const: Int -> entry to const }
)
.flatMapSingle { (entry, const) -> mapper(const, entry) }
}
@Test
fun `flat map with async side effect`() {
val constSource = Single.fromCallable { 2 }
val entrySource = Flowable.fromIterable((1L..5L))
process(constSource, entrySource)
.toList()
.test()
.await()
// f = const * entry + counter
// where counter starts from -1 when const is an odd number
.assertResult(listOf(2L, 5L, 8L, 11L, 14L))
process(constSource, entrySource)
.toList()
.test()
.await()
.assertResult(listOf(2L, 5L, 8L, 11L, 14L)) // will fail
}
这个问题有更好的解决方案吗?
答案 0 :(得分:0)
虽然您可以在读写此计数时锁定任意对象,但可以采用一种更简单,实用的方法。
天真的解决方案是使用
add_filter( 'bloginfo_url', 'your_callback' )
...假设您正在使用RxKotlin。 (这使lambda变得更简单,我们不必添加SAM conversion。)
,但这将不起作用,因为Observables.combineLatest(
Observable.range(0, Int.MAX_VALUE),
source
) { index, item -> const * item - (index and 1) }
将OOM,因为它将立即尝试从Observable.range
到0
发出所有值,因此我们只想发出on需求,因此我们可以改用MAX_VALUE
,它应该可以正常工作。
Flowable
忽略晦涩的按位运算,为了简洁起见,我在这里添加了它,因为我不知道您的代码是要做什么,或者我将这个返回奇数的Flowables.combineLatest(
Flowable.range(0, Int.MAX_VALUE),
source.toFlowable(BackPressureStrategy.BUFFER)
) { index, item -> const * item - (index and 1) }
命名为哪种方法,做最可读的事情。