You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中如何自定义函数作为distinctBy方法的参数?

Kotlin中如何自定义函数传入distinctBy实现灵活去重

问题描述

我有一个存储员工信息的列表,之前用下面的代码通过firstName去重:

val distinctEmployee = employees.distinctBy { it.firstName }

我想自定义一个函数传入distinctBy来实现灵活的列表去重,就像用filter传入自定义函数的方式:

val highSalaryEmployee = employees.filter(salaryFilter)

fun salaryFilter(employee: Employee): Boolean {
  return employee.salary > 350000
}

但我不知道怎么把这个逻辑用到distinctBy上,尝试了下面的代码但有困惑:

val distinctEmployee = employees.distinctBy { firstNameDistinct(it) }

fun firstNameDistinct(employee: Employee): Boolean {
  return employee. // 此处应返回什么?
}

请问该如何正确实现?

解决方法

首先要明确distinctBy和filter的参数逻辑差异:

  • filter接收的是返回Boolean的函数,用来判断元素是否保留;
  • distinctBy接收的是返回任意类型值的函数,这个返回值会作为"去重依据"——只要两个元素的这个返回值相等,就会被视为重复,只保留第一个出现的元素。

所以你不需要让自定义函数返回Boolean,而是返回你用来判断重复的标识值,具体实现如下:

1. 自定义单字段去重函数(比如按firstName)

// 自定义去重依据函数:返回员工的firstName作为去重标识
fun getFirstNameKey(employee: Employee): String {
    return employee.firstName
}

// 传入distinctBy使用
val distinctByFirstName = employees.distinctBy { getFirstNameKey(it) }
// 或者更简洁的方式,直接传函数引用
val distinctByFirstName = employees.distinctBy(::getFirstNameKey)

2. 自定义多字段组合去重(比如按firstName+lastName)

如果需要更复杂的去重逻辑,比如同时判断姓名全拼是否重复,只需要让函数返回组合后的标识即可:

fun getFullNameKey(employee: Employee): String {
    return "${employee.firstName}${employee.lastName}"
}

val distinctByFullName = employees.distinctBy(::getFullNameKey)

3. 自定义任意逻辑的去重依据

甚至可以返回自定义数据类作为标识,只要这个类正确实现了equals和hashCode(Kotlin的数据类默认会实现):

// 定义一个数据类作为去重标识
data class EmployeeKey(val firstName: String, val department: String)

fun getEmployeeKey(employee: Employee): EmployeeKey {
    return EmployeeKey(employee.firstName, employee.department)
}

// 按"姓名+部门"组合去重
val distinctByDeptAndName = employees.distinctBy(::getEmployeeKey)

总结:distinctBy的核心是提供一个生成"唯一标识"的函数,而不是判断是否保留的条件函数,这是它和filter最本质的区别。

内容的提问来源于stack exchange,提问作者Patrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 06:09:24