如何对比两个特定结构的Map并生成关联后的新Map?
Map关联转换实现方案
核心思路
要完成从map1和map2到map3的转换,核心步骤如下:
- 遍历
map1的每一组城市ID与子城市集合列表 - 提取列表中的第二个子城市集合(注意List索引从0开始,对应
get(1)) - 遍历该子城市集合中的每个ID,到
map2中查找对应的村庄ID集合 - 将所有关联的村庄ID合并为一个Set,作为该城市ID在
map3中的值 - 处理边界情况:过滤列表长度不足2的城市、忽略
map2中不存在的子城市ID
代码实现
方式一:Java 8+ Stream API(简洁高效)
import java.util.*; import java.util.stream.Collectors; public class MapConverter { public static Map<Long, Set<Long>> convertToCityVillageMap(Map<Long, List<Set<Long>>> citySubtierMap, Map<Long, Set<Long>> subtierVillageMap) { return citySubtierMap.entrySet().stream() // 过滤掉列表为空或长度不足2的城市 .filter(entry -> entry.getValue() != null && entry.getValue().size() >= 2) .collect(Collectors.toMap( Map.Entry::getKey, entry -> entry.getValue().get(1).stream() // 根据子城市ID获取村庄集合 .map(subtierVillageMap::get) // 过滤map2中不存在的子城市对应的null值 .filter(Objects::nonNull) // 将多个村庄集合展开为单个流 .flatMap(Set::stream) // 收集为去重的村庄ID集合 .collect(Collectors.toSet()) )); } // 测试示例 public static void main(String[] args) { // 构建测试用map1 Map<Long, List<Set<Long>>> map1 = new HashMap<>(); map1.put(1L, Arrays.asList( new HashSet<>(Arrays.asList(10L, 11L)), new HashSet<>(Arrays.asList(2L, 3L)) )); map1.put(2L, Arrays.asList( new HashSet<>(Arrays.asList(20L)), new HashSet<>(Arrays.asList(4L)) )); // 这个城市的列表只有1个元素,会被过滤 map1.put(3L, Collections.singletonList(new HashSet<>(Arrays.asList(30L)))); // 构建测试用map2 Map<Long, Set<Long>> map2 = new HashMap<>(); map2.put(2L, new HashSet<>(Arrays.asList(201L, 202L))); map2.put(3L, new HashSet<>(Arrays.asList(301L))); map2.put(4L, new HashSet<>(Arrays.asList(401L, 402L, 403L))); Map<Long, Set<Long>> map3 = convertToCityVillageMap(map1, map2); System.out.println(map3); // 输出结果:{1=[201, 202, 301], 2=[401, 402, 403]} } }
方式二:传统循环(直观易懂)
如果不熟悉Stream API,也可以用传统循环实现:
import java.util.*; public class MapConverterLoop { public static Map<Long, Set<Long>> convertToCityVillageMap(Map<Long, List<Set<Long>>> citySubtierMap, Map<Long, Set<Long>> subtierVillageMap) { Map<Long, Set<Long>> cityVillageMap = new HashMap<>(); for (Map.Entry<Long, List<Set<Long>>> entry : citySubtierMap.entrySet()) { Long cityId = entry.getKey(); List<Set<Long>> subtierList = entry.getValue(); // 跳过无效的列表 if (subtierList == null || subtierList.size() < 2) { continue; } Set<Long> subtierIds = subtierList.get(1); Set<Long> villageIds = new HashSet<>(); // 遍历子城市ID,合并对应的村庄ID for (Long subtierId : subtierIds) { Set<Long> villages = subtierVillageMap.get(subtierId); if (villages != null) { villageIds.addAll(villages); } } // 可以选择只保留有村庄关联的城市,或者直接放入空Set if (!villageIds.isEmpty()) { cityVillageMap.put(cityId, villageIds); } } return cityVillageMap; } }
关键注意事项
- 索引正确性:List的索引从0开始,需求中的“第二个Set元素”对应
get(1),务必确认业务逻辑中的列表顺序是否符合预期 - 空值防护:必须检查
map1的列表是否为null、长度是否足够,以及map2中是否存在子城市ID,避免抛出NullPointerException - 去重处理:使用
HashSet存储村庄ID会自动去重,如果业务需要保留重复值(极少场景),可以替换为ArrayList并调整收集逻辑 - 线程安全:如果在多线程环境下使用,建议替换为
ConcurrentHashMap、CopyOnWriteArraySet等线程安全集合
内容的提问来源于stack exchange,提问作者Klaus
相关产品推荐
相关产品推荐

