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

Kotlin如何合并列表同类项、聚合字段值并收集关联设备列表

Kotlin实现JSON分类聚合方案

原始输入JSON结构

{
"status": [
    {
        "conferencing": {
            "nrOfRxBytes": 1142294,
            "nrOfTxBytes": 368502,
            "CategoryActiveTime": 9625,
            "Active": true
        },
        "social_media": {
            "nrOfRxBytes": 163156131,
            "nrOfTxBytes": 1438337,
            "CategoryActiveTime": 10406,
            "Active": true
        },
        "media_streaming": {
            "nrOfRxBytes": 5065342,
            "nrOfTxBytes": 312250,
            "CategoryActiveTime": 213,
            "Active": false
        },
        "Device": "BE:A0:FE:74:39:C1"
    },
    {
        "conferencing": {
            "nrOfRxBytes": 58534,
            "nrOfTxBytes": 24615,
            "CategoryActiveTime": 10343,
            "Active": true
        },
        "social_media": {
            "nrOfRxBytes": 5618,
            "nrOfTxBytes": 2731,
            "CategoryActiveTime": 14308,
            "Active": true
        },
        "media_streaming": {
            "nrOfRxBytes": 747,
            "nrOfTxBytes": 397,
            "CategoryActiveTime": 448,
            "Active": false
        },
        "education": {
            "nrOfRxBytes": 404,
            "nrOfTxBytes": 260,
            "CategoryActiveTime": 419,
            "Active": false
        },
        "Device": "AC:12:03:EC:9B:D1"
    }
]
}

需求说明

需要对education/conferencing/social_media/media_streaming等同名分类做合并处理:

  • 对分类下的nrOfRxBytes/nrOfTxBytes/CategoryActiveTime数值字段做累加聚合
  • 收集每个分类关联的所有Device值组成列表
  • Active字段只要分类下有任意一个设备的该分类为活跃状态即保留为true

期望输出结构示例:

[{
    "name":"conferencing",
    "nrOfRxBytes": 1200828,
    "nrOfTxBytes": 393117,
    "CategoryActiveTime": 19968,
    "Active": true,
    "Device": ["AC:12:03:EC:9B:D1","BE:A0:FE:74:39:C1"]
},...]

现有待修正代码

原有数据类定义

@Parcelize
data class ServicesIdCategory(
    var name: String = "",
    val nrOfRxBytes: Int = 0,
    val nrOfTxBytes: Int = 0,
    val CategoryActiveTime: Int = 0,
    val Active: Boolean = false,
    var Device: String = ""
) : Parcelable

原有解析方法

fun getLiveServicesId(response: JSONArray): Array<ServicesIdCategory> {
    val array = mutableListOf<DeviceServicesId>()
    var categories = mutableListOf<ServicesIdCategory>()
    var category = ServicesIdCategory()
    val gson = Gson()

    for (i in 0 until response.length()) {
        val obj = response.getJSONObject(i)
        val namesArr = obj.names()
        if (namesArr != null) {
            for (j in 0 until namesArr.length()) {
                if (namesArr[j].toString() != "Device") {
                    val categoryJson = obj.optString(
                        namesArr[j].toString(), ""
                    )
                    try {
                        category = gson.fromJson(categoryJson, ServicesIdCategory::class.java)
                        category.name = namesArr[j].toString()
                    } catch (e: JsonSyntaxException) {
                    }
                }
                category.Device = obj.optString("Device")
                categories.add(category)
            }
        }
        val deviceServiceId = gson.fromJson(obj.toString(), DeviceServicesId::class.java)
        deviceServiceId.servicesIdCategory = categories.toTypedArray()
        array.add(deviceServiceId)
    }
    return categories.toTypedArray()
}

现有代码未实现同类项合并、数值聚合、设备列表收集逻辑。

正确实现步骤

1. 修正数据类定义

首先调整字段类型适配需求:

  • 数值字段改为Long避免大数值溢出
  • Device字段改为List<String>存储关联设备列表
@Parcelize
data class ServicesIdCategory(
    val name: String = "",
    val nrOfRxBytes: Long = 0L,
    val nrOfTxBytes: Long = 0L,
    val CategoryActiveTime: Long = 0L,
    val Active: Boolean = false,
    val Device: List<String> = emptyList()
) : Parcelable

// 用于解析单设备下单个分类的原始结构
private data class RawCategoryMetric(
    val nrOfRxBytes: Long = 0L,
    val nrOfTxBytes: Long = 0L,
    val CategoryActiveTime: Long = 0L,
    val Active: Boolean = false
)

2. 实现解析+聚合逻辑

利用Kotlin标准库的groupBy做分类聚合,避免手动维护映射表,逻辑更简洁:

import org.json.JSONArray
import org.json.JSONObject
import com.google.gson.Gson

fun getLiveServicesId(statusArray: JSONArray): Array<ServicesIdCategory> {
    val gson = Gson()
    // 第一步:扁平化所有(分类名、指标、设备MAC)三元组
    val flatCategoryList = mutableListOf<Triple<String, RawCategoryMetric, String>>()

    for (i in 0 until statusArray.length()) {
        val deviceObj = statusArray.getJSONObject(i)
        val deviceMac = deviceObj.optString("Device")
        val keys = deviceObj.keys()
        while (keys.hasNext()) {
            val key = keys.next()
            // 跳过Device字段,其余都是分类项
            if (key == "Device") continue
            runCatching {
                val metric = gson.fromJson(
                    deviceObj.getJSONObject(key).toString(),
                    RawCategoryMetric::class.java
                )
                flatCategoryList.add(Triple(key, metric, deviceMac))
            }
        }
    }

    // 第二步:按分类名分组聚合
    return flatCategoryList
        .groupBy { it.first } // 按分类名分组
        .map { (categoryName, groupItems) ->
            // 累加数值字段
            val totalRx = groupItems.sumOf { it.second.nrOfRxBytes }
            val totalTx = groupItems.sumOf { it.second.nrOfTxBytes }
            val totalActiveTime = groupItems.sumOf { it.second.CategoryActiveTime }
            // 只要任意一个设备该分类活跃,就标记为true
            val isActive = groupItems.any { it.second.Active }
            // 收集关联设备并去重
            val deviceList = groupItems.map { it.third }.distinct()

            ServicesIdCategory(
                name = categoryName,
                nrOfRxBytes = totalRx,
                nrOfTxBytes = totalTx,
                CategoryActiveTime = totalActiveTime,
                Active = isActive,
                Device = deviceList
            )
        }
        .toTypedArray()
}

实现说明

  • 用runCatching包裹单分类解析逻辑,避免单个字段格式错误导致整个解析流程中断
  • 设备列表加distinct()做去重,避免同一设备重复上报同分类时出现重复MAC
  • 数值字段统一用Long类型,避免流量值过大出现Int溢出问题
  • Active字段采用any聚合,只要有一个设备该分类处于活跃状态,合并后的分类就标记为活跃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:12:34