Kotlin异步数据处理乱序及索引越界问题排查求助
数据爬取乱序与索引越界问题解决
核心问题原因
- HashMap无序导致表头与数据不匹配:你用
HashMap<String, ArrayList<String>>存储表头列,HashMap的key是无序的,dataMap.keys.toList()得到的顺序和HTML表头的实际顺序完全随机,这直接导致后续单元格数据被塞到错误的列里。 - 循环索引越界:
for (i in 0..row.getElementsByTag("td").size)是闭区间循环,假设一行有n个td,i会从0取到n,而td数组的索引范围是0到n-1,当i=n时就会触发索引越界,同时也会多执行一次循环,导致最后一个key被重复赋值空数据。 - 异步并行度限制无效:你的
limitedParallelism(1)根本没解决问题,因为openinsiderGetData是同步执行的,异步只是把它放到后台线程跑,和数据乱序完全无关。
修正后的代码
修复数据爬取方法
private fun openinsiderGetData(): DataFrame<Any> { val doc = Jsoup.connect("http://openinsider.com/search?q=TSLA").get() val table = doc.select(".tinytable") // 用LinkedHashMap保证表头顺序和HTML里的一致 val dataMap = LinkedHashMap<String, ArrayList<String>>() // 提取表头并按顺序存入LinkedHashMap table.select("thead tr").forEach { row -> row.getElementsByTag("th").forEach { cell -> dataMap[cell.text()] = ArrayList() } } val keys = dataMap.keys.toList() // 现在keys顺序和表头完全一致 Log.d("Keys", keys.toString()) // 处理表体数据 table.select("tbody tr").forEach { row -> val cells = row.getElementsByTag("td") var index = 0 // 用until代替..,避免索引越界(0到cells.size-1) for (i in 0 until cells.size) { if (index >= keys.size) break // 额外防护,避免表头和列数不匹配 val key = keys[index] val cellText = cells[i].text() Log.d("Key", key) Log.d("CELL TEXT:", cellText) dataMap[key]?.add(cellText) index += 1 Log.d("DATA SO FAR", dataMap.toString()) } } Log.d("Map:", dataMap.toString()) val df = emptyDataFrame<Any>() // 按表头顺序添加列,保证DataFrame列顺序正确 for (key in keys) { val column = columnOf(dataMap[key]) named key df.add(column) } Log.d("Dataframe:", df.toString()) return df }
简化异步处理(并行度限制可移除)
private fun setupData() { lifecycleScope.launch { withContext(Dispatchers.Default) { data = openinsiderGetData() val rows = data.values(byRows=true) Log.d("ROWS:", rows.toString()) } // 回到主线程绘制表格 withContext(Dispatchers.Main) { // TODO: 绘制表格的逻辑 } } }
额外说明
- 用
LinkedHashMap替代HashMap是关键,它会保留键的插入顺序,也就是HTML表头的顺序,这样每个单元格数据都会对应到正确的列。 - 循环里的
0 until cells.size确保不会访问超出数组范围的索引,解决越界问题。 - 最后构建DataFrame时用
keys(表头顺序列表)遍历,而不是dataMap.keys,保证DataFrame的列顺序和原始表格一致。
内容的提问来源于stack exchange,提问作者David Frick
相关产品推荐
相关产品推荐

