如何从HashMap<String, Double>集合计算平均值并找最小平均键
问题描述
我从MultiMap中获取到一个HashMap<String, Double>的集合,需要计算各Map键对应值的平均值,并找出平均值最小的键。简化测试数据如下:
HashMap<A1, 2.0>
HashMap<A2, 1.0>
HashMap<A1, 3.0>
HashMap<A2, 1.0>
实际业务场景是处理端点接收的设备-网关RSSI数据,数据格式如下:
{ "Gateway": "G1", "Device": "D1", "position": {"rssi": 1} }, { "Gateway": "G2", "Device": "D1", "position": {"rssi": 3} }, { "Gateway": "G1", "Device": "D1", "position": {"rssi": 2} }, { "Gateway": "G2", "Device": "D1", "position": {"rssi": 5} }, { "Gateway": "G1", "Device": "D1", "position": {"rssi": 4} }, { "Gateway": "G2", "Device": "D1", "position": {"rssi": 6} }, ... { "Gateway": "G1", "Device": "D2", "position": {"rssi": 3} }, { "Gateway": "G2", "Device": "D2", "position": {"rssi": 2} }
最终需要计算类似以下格式的平均值,并判断设备优先连接的网关:
D1-> G1: {1,2,4} => 7/3 = 2.3
D1-> G2: {3,5,6} => 14/3 = 4.6
思路提示
第一步:数据聚合(按分组键收集所有对应值)
不管是简化测试数据还是实际业务数据,核心都是先把相同分组键对应的所有值归集到一起:
- 测试场景:用
Map<String, List<Double>>作为统计容器,键是A1/A2这类标识,值是对应Double类型的数值列表 - 实际业务场景:用嵌套Map
Map<String, Map<String, List<Integer>>>,外层键是设备ID,内层键是网关ID,值是该设备对应网关的RSSI数值列表 - 遍历所有输入数据,将对应值添加到分组键的列表中
第二步:计算平均值并筛选目标结果
- 遍历统计容器,对每个分组键的数值列表计算总和,再除以列表长度得到平均值
- 测试场景:记录所有键的平均值,找出其中最小的那个对应的键
- 实际业务场景:对每个设备下的网关平均值进行比较,根据RSSI信号规则(通常数值越小信号越强),找出平均值最小的网关,即为该设备优先连接的对象
伪代码示例
测试场景伪代码
// 从MultiMap提取的HashMap集合 Collection<HashMap<String, Double>> mapCollection = ...; // 初始化统计容器:键 -> 对应值列表 Map<String, List<Double>> valueMap = new HashMap<>(); // 聚合数据 for (HashMap<String, Double> map : mapCollection) { for (Map.Entry<String, Double> entry : map.entrySet()) { String key = entry.getKey(); Double value = entry.getValue(); // 键不存在则创建新列表,再添加值 valueMap.computeIfAbsent(key, k -> new ArrayList<>()).add(value); } } // 计算平均值并找最小键 double minAvg = Double.MAX_VALUE; String minKey = null; for (Map.Entry<String, List<Double>> entry : valueMap.entrySet()) { String key = entry.getKey(); List<Double> values = entry.getValue(); double sum = 0; for (Double val : values) { sum += val; } double avg = sum / values.size(); if (avg < minAvg) { minAvg = avg; minKey = key; } } // 输出结果 System.out.println("平均值最小的键:" + minKey + ",平均值:" + minAvg);
实际业务场景伪代码
// 输入的设备网关数据列表 List<Map<String, Object>> deviceDataList = ...; // 初始化统计容器:设备ID -> 网关ID -> RSSI列表 Map<String, Map<String, List<Integer>>> deviceGatewayRssiMap = new HashMap<>(); // 聚合数据 for (Map<String, Object> data : deviceDataList) { String device = (String) data.get("Device"); String gateway = (String) data.get("Gateway"); Map<String, Integer> position = (Map<String, Integer>) data.get("position"); int rssi = position.get("rssi"); // 层级初始化,避免空指针 deviceGatewayRssiMap.computeIfAbsent(device, k -> new HashMap<>()); deviceGatewayRssiMap.get(device).computeIfAbsent(gateway, k -> new ArrayList<>()); // 添加RSSI值到对应列表 deviceGatewayRssiMap.get(device).get(gateway).add(rssi); } // 计算平均值并判断设备优先网关 for (Map.Entry<String, Map<String, List<Integer>>> deviceEntry : deviceGatewayRssiMap.entrySet()) { String device = deviceEntry.getKey(); Map<String, List<Integer>> gatewayRssiMap = deviceEntry.getValue(); double minAvg = Double.MAX_VALUE; String preferredGateway = null; for (Map.Entry<String, List<Integer>> gatewayEntry : gatewayRssiMap.entrySet()) { String gateway = gatewayEntry.getKey(); List<Integer> rssis = gatewayEntry.getValue(); int sum = 0; for (int rssi : rssis) { sum += rssi; } double avg = (double) sum / rssis.size(); System.out.println(device + "->" + gateway + ": " + rssis + " => " + sum + "/" + rssis.size() + " = " + String.format("%.1f", avg)); // 假设RSSI越小信号越好,筛选平均值最小的网关 if (avg < minAvg) { minAvg = avg; preferredGateway = gateway; } } System.out.println("设备" + device + "优先连接的网关:" + preferredGateway); }
内容的提问来源于stack exchange,提问作者user565
相关产品推荐
相关产品推荐

