如何使用声明性Kotlin在两个不同类型的列表之间复制属性?

sur*_*s02 0 foreach android declarative kotlin

上下文

使用在一个科特林声明性方法,需要一个单一的复制name属性从ListUser对象到ListUserDetail基于匹配的对象id的属性,如下所示:

val users = Arrays.asList(
        User(1, "a"),
        User(2, "b")
)
val details = Arrays.asList(
        UserDetail(1),
        UserDetail(2)
)
val detailsWithName = copyNameToUser(users, details)
Run Code Online (Sandbox Code Playgroud)

模型是:

class User {
    var id = -1;
    var name = "" // given for all Users
    constructor(id: Int, name: String)
    // ...
}
class UserDetail {
    var id = -1;
    var name = "" // blank for all UserDetails
    constructor(id: Int)
    // ...
}
Run Code Online (Sandbox Code Playgroud)

问题

试图通过forEach可迭代函数使用声明方法:

fun copyNameToDetails(users: List<User>, details: List<UserDetail>): List<UserDetail> {
    details.forEach(d ->
        users.forEach(u ->
            if (d.id == u.id) {
                d.name = u.name
            }
        )
    )
    return details
}
Run Code Online (Sandbox Code Playgroud)

这可以用Java实现,如下所示:

private static List<UserDetail> copyNameToDetails(List<User> users, List<UserDetail> details)   {
    for (UserDetail d: details) {
        for (User u : users) {
            if (d.id == u.id) {
                d.name = u.name;
            }
        }
    }
    return details;
}
Run Code Online (Sandbox Code Playgroud)

如何使用声明式方法在Kotlin中完成?

Ser*_*tin 5

您在两个列表(users.size * details.size)上进行了太多迭代,因此创建一个hashmap可以修复它:

fun copyNameToUsers(users: List<User>, details: List<UserDetail>): List<UserDetail> {
    val usersById = users.associate { it.id to it }
    details.forEach { d ->
        usersById[d.id]?.let { d.name = it.name }
    }

    return details
}
Run Code Online (Sandbox Code Playgroud)