Kotlin中群聚Map的保序性

jhkqcmku  于 2022-12-13  发布在  Kotlin
关注(0)|答案(2)|浏览(201)

我使用groupingByaggregate来处理一个项目列表,并将它们分组为对。输入列表的顺序很重要,结果列表也应该是有序的。
aggregate会传回Map,表示不保留行程顺序。
示例:

data class Foo(val a: Int, val b: String)

    val r1 = Foo(1, "a")
    val r2 = Foo(1, "b")
    val r3 = Foo(2, "c")
    val r4 = Foo(2, "d")
    val r5 = Foo(2, "e")
    val records = listOf(r1, r2, r3, r4, r5)

    val result = records.groupingBy { it.a }
        .aggregate { _, acc: Pair<Int, List<String>>?, element, _ ->
            if (acc == null) {
                element.a to listOf(element.b)
            } else {
                acc.first to acc.second + element.b
            }
        }.values.toList()

    println(result)

返回[(1, [a, b]), (2, [c, d, e])]-这是正确的顺序,但它是否 * 有保证 *?
请注意,这是一个简单的示例,可以按a排序-但这不是解决方案,因为记录排序是由函数的用户提供的。

r9f1avp5

r9f1avp51#

aggregate的文档不能保证这一点,但是mutableMapOf的文档可以保证这一点。所以我会使用aggregateTo(mutableMapOf()) { /*...*/ }来保证你的代码的未来性。事实上,他们不保证这一点意味着他们要么忘记了,要么他们故意想在未来保持切换底层实现的选择。

llycmphe

llycmphe2#

如果要确保聚合结果的对已排序,可以执行以下操作:

fun main() {
    data class Foo(val a: Int, val b: String)

    val r1 = Foo(2, "a")
    val r2 = Foo(2, "b")
    val r3 = Foo(1, "c")
    val r4 = Foo(1, "d")
    val r5 = Foo(2, "e")
    val records = listOf(r1, r2, r3, r4, r5)

    val result = records.groupingBy { it.a }
        .aggregate { _, acc: Pair<Int, List<String>>?, element, _ ->
            if (acc == null) {
                element.a to listOf(element.b)
            } else {
                acc.first to acc.second + element.b
            }
        }.values.sortedBy {it.first}.toList()

    println(result)
}

这将输出[(1, [c, d]), (2, [a, b, e])]

相关问题