Kotlin - 如何正确并行处理数据?

问题描述 投票:0回答:1

我正在抓取一个网站以获取信息。片段包含两个检索数据然后绘制数据的方法。我必须异步处理数据以防止主线程被锁定。但是,当我运行代码时,很明显异步数据处理发生无序,这导致某些索引超出范围。我不确定该怎么办。我试图限制并行性,但没有帮助。我错过了什么?

 private fun openinsiderGetData(): DataFrame<Any> {
        val doc = Jsoup.connect("http://openinsider.com/search?q=TSLA").get()
        val table = doc.select(".tinytable")
        val dataMap =  HashMap<String, ArrayList<String>>()


        table.select("thead").select("tr").forEach {row ->
            row.getElementsByTag("th").forEach { cell ->
                dataMap[cell.text()] = ArrayList<String>()
            }
        }
        // Get the table body cells
        val keys = dataMap.keys.toList()
        Log.d("Keys", keys.toString())

        table.select("tbody").select("tr").forEach {row ->
            var index = 0
            for (i in 0..row.getElementsByTag("td").size) {
                val key = keys[index]
                Log.d("Key", key)
                index += 1
                Log.d("CELL TEXT:", row.getElementsByTag("td")[i].text())
                dataMap[key]?.add(row.getElementsByTag("td")[i].text())
                Log.d("DATA SO FAR", dataMap.toString())
            }
        }
        Log.d("Map:", dataMap.toString())

        val df = emptyDataFrame<Any>()
        for (key in dataMap.keys) {
            val column = columnOf(dataMap[key]) named key
            df.add(column)
        }
        Log.d("Dataframe:", df.toString())
 
        // process the data further
        return df
    }

}

  private fun setupData() {
        lifecycleScope.launch {
            withContext(Dispatchers.Default.limitedParallelism(1)) {
                data = openinsiderGetData()
                val rows = data.values(byRows=true)
                Log.d("ROWS:", rows.toString())
            }
// TODO - Refactor Draw the table

我的数据日志给出:

{Insider Name=[D], Filing Date=[2023-08-08 20:01:17], 1w=[2023-08-04], Ticker=[TSLA], Title=[Taneja Vaibhav], Trade Type=[CFO, CAO], ΔOwn=[S - Sale+OE], 1d=[$261.00], Owned=[-4,000], Price=[104,504], Qty=[-4%], 6m=[-$1,044,000], X=[], Value=[], Trade Date=[], 1m=[]}

这显然是不正常的。我对这种情况如何发生以及如何预防感到困惑。

kotlin asynchronous
1个回答
0
投票

您的问题与并行处理数据无关。事实上,无论您是否限制并行性,您都不会在这里并行处理任何内容。您只启动了一个协程,因此没有任何东西可以并行运行。

正如在上一个问题中一样,您似乎假设映射中的键使用某种特定的顺序,它们有自己的索引。他们一般不会。将数据添加到地图后,如果我们获取其键,我们将以随机顺序获取它们。

解决该问题的一种方法是使用

LinkedHashMap
而不是
HashMap
。这是映射的特殊实现,它保留插入顺序。更好的是,使用
mutableMapOf()
函数,这是在 Kotlin 中创建地图的标准方法,在它的下面使用
LinkedHashMap
mutableMapOf<String, List<String>>()

更明确的解决方案是在解析

thead
时创建一个键列表。或者我们可以将
ArrayList
对象存储在地图和列表中:

val dataMap =  HashMap<String, ArrayList<String>>()
val dataList =  ArrayList<ArrayList<String>>()

// while parsing thead:
val list = ArrayList<String>()
dataMap[cell.text()] = list
dataList += list


// while parsing the data:
dataList[index]?.add(row.getElementsByTag("td")[i].text())
© www.soinside.com 2019 - 2024. All rights reserved.