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

Kotlin中MutableList存储Edibles对象时无法使用removeAll去重及元素频次统计问题

问题分析与解决方案

嘿,我来帮你梳理下问题和对应的解决思路:

1. 原代码失效的核心原因

  • 相等性判断逻辑错误:Kotlin中普通自定义类的==默认是基于对象引用的(和===效果一致)——也就是说,哪怕两个Edibles对象的name完全相同,只要是不同实例,it == order[0]就会返回false。这直接导致count统计结果错误,removeAll也找不到要移除的元素。
  • 循环修改列表的风险:你在for循环里直接修改原order列表(调用removeAll),这会破坏迭代器的正常遍历逻辑,很容易触发ConcurrentModificationException,或者导致元素被跳过。
  • 对Collection接口的误解:你完全不需要让Edibles实现Collection接口——这个接口是给容器类(比如List、Set)设计的,你的Edibles是单个物品类,和它没有任何关联。

2. 快速修复方案

第一步:让Edibles支持正确的相等判断

最简单的方式是把Edibles改成data class,Kotlin会自动帮你生成基于主构造函数属性的equals()、hashCode()方法,这样相同name(和price)的对象会被判定为相等:

data class Edibles(val name: String, val price: Double): Serializable { }

如果你的需求是「只要name相同就算同一种物品(不管price差异)」,可以手动重写equals()和hashCode(),只基于name判断:

class Edibles(val name: String, val price: Double): Serializable {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false
        other as Edibles
        return name == other.name
    }

    override fun hashCode(): Int {
        return name.hashCode()
    }
}

第二步:用Kotlin标准库优雅统计次数

完全不需要手动循环修改列表,用groupBy就能轻松分组统计,代码简洁又安全:

// 按物品名称分组,统计每组的数量
val orderGroups = order.groupBy { it.name }
// 转换成你需要的字符串格式
val totalOrder = orderGroups.entries.joinToString("\n") { "${it.value.size}x ${it.key}" }

这段代码会生成你想要的格式:

9x Juice 
5x Steaks 
4x Salads

如果需要按Edibles的完整属性(name+price)分组,直接用it作为分组键即可:

val orderGroups = order.groupBy { it }
val totalOrder = orderGroups.entries.joinToString("\n") { "${it.value.size}x ${it.key.name}" }

3. 这个方案的优势

  • 无副作用:不会修改原order列表,避免了遍历过程中修改容器的风险。
  • 代码简洁:利用Kotlin标准库函数,省去了手动计数、移除元素的繁琐逻辑。
  • 性能更优:groupBy只需要遍历列表一次,比原代码中每次循环都调用count(多次遍历)效率高很多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 21:49:07