Kotlin 如何基于ID合并两个对象列表?

Kotlin 如何基于ID合并两个对象列表?,kotlin,Kotlin,我有两张单子。一个名为oldList并包含旧数据,第二个名为updateList并包含一组更新 我想用这些规则创建一个新列表: 从旧列表中获取所有数据 使用唯一的id 如果更新项目的id已存在于oldData中,请将其替换 我想出了一个简单的代码: Item.kt data class Item (val id: String, val text: String) fun main() { val oldList: List<Item> = listOf(

我有两张单子。一个名为
oldList
并包含旧数据,第二个名为
updateList
并包含一组更新

我想用这些规则创建一个新列表:

  • 旧列表中获取所有数据
  • 使用唯一的
    id
  • 如果更新项目的
    id
    已存在于
    oldData
    中,请将其替换
我想出了一个简单的代码:

Item.kt

data class Item (val id: String, val text: String)
fun main() {

    val oldList: List<Item> = listOf(
        Item("aaa1", "aaa2"),
        Item("bbb1", "bbb2"),
        Item("ddd1", "ddd2"))

    val updateList: List<Item> = listOf(
        Item("aaa1", "aaa3"),
        Item("ccc1", "ccc2"))

    val resultList = oldList.toMutableList()

    for (item in updateList) {
        val index = oldList.indexOfFirst { it.id == item.id }
        if (index < 0) {
            resultList.add(item)
        } else {
            resultList[index] = item
        }
    }

    println(resultList)
}
Main.kt

data class Item (val id: String, val text: String)
fun main() {

    val oldList: List<Item> = listOf(
        Item("aaa1", "aaa2"),
        Item("bbb1", "bbb2"),
        Item("ddd1", "ddd2"))

    val updateList: List<Item> = listOf(
        Item("aaa1", "aaa3"),
        Item("ccc1", "ccc2"))

    val resultList = oldList.toMutableList()

    for (item in updateList) {
        val index = oldList.indexOfFirst { it.id == item.id }
        if (index < 0) {
            resultList.add(item)
        } else {
            resultList[index] = item
        }
    }

    println(resultList)
}
fun main(){
val oldList:List=listOf(
项目(“aaa1”、“aaa2”),
项目(“bbb1”、“bbb2”),
项目(“ddd1”、“ddd2”))
val updateList:List=listOf(
项目(“aaa1”、“aaa3”),
项目(“ccc1”、“ccc2”))
val resultList=oldList.toMutableList()
对于(updateList中的项){
val index=oldList.indexOfFirst{it.id==item.id}
如果(指数<0){
结果列表.添加(项)
}否则{
结果列表[索引]=项目
}
}
println(结果列表)
}

这很好,但我可以想象它的效率很低,可能还有一些不错的
Kotlin
习惯用法。有更好的解决方案吗?

如果原始顺序无关紧要,您可以组合列表,将新值放在第一位,以便在
调用中区分它们:

val resultList = (updateList + oldList).distinctBy(Item::id)
如果顺序与您描述的完全一样重要,则可以在组合这两个列表之前将其转换为映射。当使用
+
组合到映射时,第二个映射中的项目优先,但保留第一个映射中的顺序

val resultList = 
    (oldList.associateBy(Item::id) + updateList.associateBy(Item::id)).values.toList()

如果您重写equals和hashcode以仅使用id,就像您的类使用id一样,这似乎是正确的做法,那么我不确定它是否是数据类

data class Item(val id: String,
                  val text: String) {

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other?.javaClass != javaClass) return false

        other as Item

        if (id != other.id) return false

        return true
    }

    override fun hashCode(): Int {
        return id.hashCode()
    }
}
然后您可以将updateList与旧列表合并

fun main() {

    val oldList: List<Item> = listOf(
        Item("aaa1", "aaa2"),
        Item("bbb1", "bbb2"),
        Item("ddd1", "ddd2"))

    val updateList: List<Item> = listOf(
        Item("aaa1", "aaa3"),
        Item("ccc1", "ccc2"))

    val resultList = updateList.union(oldList)

    println(resultList)
}
fun main(){
val oldList:List=listOf(
项目(“aaa1”、“aaa2”),
项目(“bbb1”、“bbb2”),
项目(“ddd1”、“ddd2”))
val updateList:List=listOf(
项目(“aaa1”、“aaa3”),
项目(“ccc1”、“ccc2”))
val resultList=updateList.union(旧列表)
println(结果列表)
}

您可以使用
区分方法:

val resultList = (updateList + oldList).distinctBy { it.id }

distinctBy
所做的是返回一个新列表,其中只包含由提供的lambda返回的具有不同键的元素。但是,您必须记住,元素的顺序很重要,使用给定键的第一个遇到的项将保留在结果列表中,其他项将被忽略。

没有尝试过这一点,但类似于
(oldList+updateList).groupBy{it.id}.mapValues{it.last}
?如果原来的订单真的重要呢?呵呵,昨天我自己想出了这个。回答得好,竖起大拇指!