如何根据 Kotlin 中的公共值字段从两个不同的 ArrayList 对象创建排序的合并列表?

How to create a sorted merged list from two diffrent ArrayList of Objects based on a common value field in Kotlin?

提问人:RKB 提问时间:2/18/2021 更新时间:2/18/2021 访问量:204

问:

我有两个不同 Data 类的 ArrayList,如下所示:

class Record{
    var id: Long = 0
    var RecordId: Int = 0
    var Record: String? = null
    var title: String? = null
    var description: String? = null
    var longDate: Long = 0
}

class Type{
    var id: Long = 0
    var typeId: Int = 0
    var subTypeId: Int = 0
    var typeString: String? = null
    var longDate: Long = 0
}

var recordsList: ArrayList<Record>
var typesList: ArrayList<Type>

现在,我想要这两个的合并列表,该列表将根据两个对象中的公共字段进行排序,即 .我尝试过等等,但无法达到预期的结果。longDate.associate , sortedBy, sortedWith(compareBy<>)

在这里,还有一点需要注意的是,在比较两个列表时,其中一个列表可能是空的。

Kotlin 数组列表 进行排序比较

评论

1赞 Tenfour04 2/18/2021
你想要一个列表,列出你必须在哪里施放你从中检索到的物品?Any
0赞 RKB 2/18/2021
是的,确切地说,我想要一个列表,然后我可以在适配器中使用Any
1赞 Adam Millerchip 2/18/2021
您尝试对合并的列表做什么?感觉像是一个 XY 问题 - 也许有另一种方法。
0赞 RKB 2/18/2021
@AdamMillerchip,我的应用程序中有一个用例,我需要显示由上述两个列表组成的列表,并按照问题中所述的排序方式显示。请您简要介绍一下替代方法,我将不胜感激。虽然我从 Tenfour04 的答案中得到了解决方案
0赞 Adam Millerchip 2/18/2021
一切都太笼统了,现在无法提出替代方案。他们为什么需要在一起?例如,它们是成对的吗?

答:

1赞 Tenfour04 2/18/2021 #1

这将产生一个所有项目按以下方式排序:List<Any>longDate

(recordsList + typesList)
    .sortedBy { 
        when (it) {
            is Record -> it.longDate
            is Type -> it.longDate
            else -> error("")
        }
    }

或者,您可以考虑创建一个具有这两个类实现的接口。这样你就不需要这个表达式了,你的 List 将是接口的类型。val longDate: Longwhen

评论

1赞 Михаил Нафталь 2/18/2021
使用 sortedBy 会更简洁
0赞 RKB 2/18/2021
这很有效,这就是我一直在寻找的东西。我创建了一个界面来避免您建议的那样。(recordsList + typesList)when
0赞 Tenfour04 2/18/2021
真的,我会让界面包含与将这两者一起呈现在列表中的所有内容。
0赞 Tenfour04 2/18/2021
谢谢,@МихаилНафталь
1赞 AlexT 2/18/2021 #2

这样的东西应该可以工作,但我个人认为这很有代码的味道。不能保证它与类型完全相同(我们知道它是,因为我们创建了模型,但编译器永远不会知道)。Record.longDateType.longDate

val result = (recordsList + typesList).sortedBy {
        when(it){
            is Record -> it.longDate
            is Type -> it.longDate
            else -> error("incompatible list element $it")
        }
    }

它的工作原理是这样的:(我已经从模型中删除了一些参数,因为它们在这里并不真正重要)

    
fun main() {
    
    val recordsList = listOf(Record().apply { longDate = 5 }, Record().apply { longDate = 3})
    val typesList =  listOf(Type().apply { longDate = 3 }, Type().apply { longDate = 2 })
    
    val result = (recordsList + typesList).sortedBy {
        when(it){
            is Record -> it.longDate
            is Type -> it.longDate
            else -> error("incompatible list element $it")
        }
    }
    
    result.forEach{
        println(it.toString())
    }
    
}


class Record{
        var longDate: Long = 0
    override fun toString(): String {
        return "Record(longDate=$longDate)"
    }
}

class Type{
    var longDate: Long = 0
    override fun toString(): String {
        return "Type(longDate=$longDate)"
    }
}

这将输出:

Type(longDate=2)
Record(longDate=3)
Type(longDate=3)
Record(longDate=5)

以一种更通用的方式做到这一点,这样你就可以创造一个有趣的方式,你从每个对象类型中说明要使用哪个属性,最有可能使用反射,我会不惜一切代价避免这种情况。

因此,我肯定会考虑一个对象是否可以继承另一个对象,或者创建一个接口,或者其他任何东西。

我将以 2 个问题结束:为什么没有构造函数?为什么是 ArrayList 而不是 list?