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

哪些场景下Kotlin的toSet方法会抛出java.lang.IllegalArgumentException

异常触发原因说明

核心根因

该异常本质是多线程并发修改集合未完全加锁导致的,你当前仅在读取markersMap的位置加了synchronized锁,只要存在任意一处修改markersMap的代码没有加同一把锁,就会触发该问题。

mapCapacity返回负数的逻辑

Kotlin标准库中mapCapacity的实现逻辑非常简单:

internal fun mapCapacity(expectedSize: Int): Int = when {
    expectedSize < 3 -> expectedSize + 1
    expectedSize < 1073741824 -> expectedSize + expectedSize / 3
    else -> 2147483647
}

它本身不会主动返回负数,只有当传入的expectedSize参数本身是负数时,最终返回结果才会是负数。这里的expectedSize就是你调用toSet()时读取的markersMap.values.size。

size为负的原因

默认的mutableMapOf返回的是线程不安全的LinkedHashMap,它的size是普通int类型变量,没有任何并发可见性或原子性保障:

  • 多线程同时修改size时会出现原子性问题,比如两个线程同时执行减元素操作,指令交错后会出现计算下溢,最终size变成负数
  • 你在持锁读取size时,其他未持锁的线程正在修改size,也可能读到更新过程中的中间值,也就是负数

当size为负时,传入mapCapacity就会得到负的初始容量,传给LinkedHashMap构造函数就会抛出你遇到的IllegalArgumentException: Illegal initial capacity: -1异常。

修复方案

  • 检查所有修改markersMap的位置,包括put、remove、clear等操作,全部加上synchronized(markersMap)锁,保证所有读写操作都持有同一把锁,彻底避免并发修改
  • 也可以直接替换为线程安全的ConcurrentHashMap实现,无需手动加锁就能避免该问题:
private val markersMap = ConcurrentHashMap<Any, Marker>()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 03:51:04