【发布时间】:2021-10-08 00:29:34
【问题描述】:
简介
假设我有一个 Kotlin 枚举类:
enum class Type {
ONE,
TWO,
THREE,
FOUR
}
以及以下数据类:
data class Item(
val name: String,
val type: Type
)
然后我有一个Single,它发出一个Items 的列表——可以通过任何方式,但出于示例目的,假设它看起来像这样:
val itemsSingle = Single.just(listOf(
Item("A", Type.ONE),
Item("B", Type.ONE),
Item("C", Type.TWO),
Item("D", Type.THREE),
))
问题
我想要实现的是拥有一个 RxJava 流,它将输出一个映射,其中键来自 Type,值是与给定 Type 值匹配的 Items 列表(其中未确定的、未排序的Items 的列表由其他一些 Single 流提供)。签名将是:
Single<Map<Type, List<Item>> // or Observable<Map<Type, List<Item>>
另一个要求是映射的键应始终耗尽 Type 枚举中的所有值,即使 itemsSingle 流不包含某些 Type 值的项目(或根本没有项目)。因此,对于提供的 itemsSingle 示例流,返回的映射应如下所示:
{
ONE: [ Item(name: "A", type: ONE), Item(name: "B", type: ONE) ],
TWO: [ Item(name: "C", type: TWO) ],
THREE: [ Item(name: "D", type: THREE) ],
FOUR: []
}
尝试
通过以上所有步骤,我已经通过以下步骤达到了预期的结果:
- 为了满足用尽所有
Type枚举值的要求,我首先创建一个映射,其中包含所有可能的Type值的空列表:
val typeValuesMap = Type.values().associate { it to emptyList<Item>() }
val typeValuesMapSingle = Single.just(typeValuesMap)
// result: {ONE=[], TWO=[], THREE=[], FOUR=[]}
- 我可以得到一张地图,其中包含来自
itemsSingle的项目,这些项目分组在各自的Type值键下:
val groupedItemsMapSingle = itemsSingle.flattenAsObservable { it }
.groupBy { it.type }
.flatMapSingle { it.toList() }
.toMap { list -> list[0].type } // the list is guaranteed to have at least one item
// result: {ONE=[Item(name=A, type=ONE), Item(name=B, type=ONE)], THREE=[Item(name=D, type=THREE)], TWO=[Item(name=C, type=TWO)]}
- 最后我可以使用 combineLatest 运算符合并两个列表,并覆盖给定
Type值的初始空项目列表:
Observable.combineLatest(
typeValuesMapSingle.flattenAsObservable { it.entries },
groupedItemsMapSingle.flattenAsObservable { it.entries }
) { a, b -> listOf(a, b) }
.defaultIfEmpty(typeValuesMap.entries.toList()) // in case itemsSingle is empty
.flatMapIterable { it }
.collect({mutableMapOf<Type, List<Item>>()}, { a, b -> a[b.key] = b.value})
// result: {FOUR=[], ONE=[Item(name=A, type=ONE), Item(name=B, type=ONE)], THREE=[Item(name=D, type=THREE)], TWO=[Item(name=C, type=TWO)]}
总结
如您所见,对于一个看似简单的操作,它的代码量相当多。所以我的问题是——有没有更简单的方法来达到我想要的结果?
【问题讨论】:
标签: kotlin enums rx-java rx-java2