如何根据ID合并两个对象列表?

时间:2019-11-11 14:38:26

标签: kotlin

我有两个列表。一个称为oldList,其中包含旧数据,第二个称为updateList,其中包含一组更新。

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

  • oldList
  • 获取所有数据
  • 使用唯一的id
  • 附加所有更新
  • 如果id中已经有oldData个更新项目,请替换

我想出了一个简单的代码:

Item.kt

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

Main.kt

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)
}

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

3 个答案:

答案 0 :(得分:2)

如果原始顺序无关紧要,则可以合并列表,并在distinctBy调用中将新值放在第一位以使它们偏爱:

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

答案 1 :(得分:1)

您可以使用distinctBy方法:

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

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

答案 2 :(得分:0)

如果您覆盖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)
}