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

Kotlin中同类型属性Set引发StackOverflow异常问题排查

问题原因分析

你遇到的StackOverflow错误,根源在于data class自动生成的hashCode/equals方法与MutableSet的特性结合,触发了无限递归:

  • Kotlin的data class会根据主构造函数里的所有属性,自动生成hashCode、equals和toString方法。你的Person类主构造函数包含neighbors(MutableSet<Person>),所以生成的hashCode会递归计算集合里每个Person的哈希值。
  • MutableSet的实现类(比如默认的LinkedHashSet)在添加元素时,会先调用元素的hashCode确定存储位置,还会调用equals检查元素是否已存在。

当你让commonNeighbor引用neighbor1/neighbor2,同时这两个又引用commonNeighbor时,就形成了循环引用:计算commonNeighbor的哈希值时,需要遍历它的neighbors里的neighbor1,而计算neighbor1的哈希值又要遍历它的neighbors里的commonNeighbor,无限递归下去直到栈溢出。

为什么替换后问题消失
  • 换成普通class:普通class不会自动生成hashCode/equals,默认使用Object的实现(基于对象引用),添加元素时不会触发递归计算。
  • 换成ArrayList:ArrayList添加元素时不会调用元素的hashCode/equals(只有调用contains、indexOf等方法时才会),所以不会触发递归。
解决方案

方案1:自定义data class的hashCode和equals,排除循环引用的属性

只基于id生成这两个方法,避免递归处理neighbors:

data class Person(
    val id: Int,
    val neighbors: MutableSet<Person> = mutableSetOf()
) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false
        other as Person
        return id == other.id
    }

    override fun hashCode(): Int {
        return id
    }
}

方案2:将neighbors移出主构造函数

这样data class自动生成的方法不会包含neighbors,也就不会触发递归:

data class Person(val id: Int) {
    val neighbors: MutableSet<Person> = mutableSetOf()
}

方案3:改用普通class(如果不需要data class的其他特性)

class Person(
    val id: Int,
    val neighbors: MutableSet<Person> = mutableSetOf()
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 09:05:20