LinkedHashMap 修改指定的Key值并且保持原有Key的顺序不变
需求:今天遇到一个数据处理的问题,我使用了LinkedHashMap集合统计数据,但是数据中出现了Key值相同的数据,因此想要把两个对象都保存起来并且不影响put的顺序。
方案1:首先查了一下LinkedHashMap类提供的方法,有修改指定Key对应的Value的,但是没找到修改Key值的(比较遗憾,不知道是自己没找到还是没提供,个人觉得这个功能挺有用的)
方案2:基于方案1,我想着那就创建一个新的LinkedHashMap对象并赋值给oldMap (oldMap = newMap),很奇怪,失败了,因为oldMap是通过引用传值方式(该方法还会返回其他数据)
方案3:基于方案2,我只能尝试将oldMap清空,然后遍历newMap向oldMap添加,结果终于成功了。
再次记录下方案1与方案2的代码:
1 @Slf4j 2 public class Main { 3 public static void main(String[] args) { 4 5 LinkedHashMap<String, Object> keyValueMap = new LinkedHashMap<>(); 6 keyValueMap.put("1", 1); 7 keyValueMap.put("2", 2); 8 keyValueMap.put("3", 3); 9 10 String newKey = "1"; 11 Integer newObject = 4; 12 13 newKey = addNewData(newKey, keyValueMap); 14 15 keyValueMap.put(newKey, newObject); 16 17 keyValueMap.entrySet().stream().forEach(entry -> log.info("key:{}, value:{}", entry.getKey(), entry.getValue())); 18 } 19 20 private static String addNewData(String newKey, LinkedHashMap<String, Object> keyValueMap) { 21 22 String nextKey = newKey; 23 24 List<String> keyList = keyValueMap.keySet().stream().collect(Collectors.toList()); 25 26 if (keyList.contains(newKey)) { 27 Integer num = getKeyNum(keyList, newKey); 28 29 LinkedHashMap<String, Object> map = replaceSpecifyKey(keyValueMap, newKey, new StringBuffer(newKey).append("_").append(++num).toString()); 30 31 // 方案1 start 32 keyValueMap = map; 33 // 方案1 end 34 35 // 方案2 start 36 keyValueMap.clear(); 37 38 map.entrySet().stream().forEach(entry -> { 39 keyValueMap.put(entry.getKey(), entry.getValue()); 40 }); 41 // 方案2 end 42 43 nextKey = new StringBuffer(newKey).append("_").append(++num).toString(); 44 } 45 46 return nextKey; 47 } 48 49 private static Integer getKeyNum(List<String> keyList, String newKey) { 50 AtomicReference<Integer> num = new AtomicReference<>(0); 51 52 keyList.stream().forEach(key -> { 53 if (key.contains("_")) { 54 num.set(Integer.parseInt(key.substring(key.lastIndexOf("_") + 1).trim())); 55 } 56 }); 57 58 return num.get(); 59 } 60 61 private static LinkedHashMap<String, Object> replaceSpecifyKey(LinkedHashMap<String, Object> keyValueMap, String specifyKey, String targetKey) { 62 LinkedHashMap<String, Object> newKeyValueMap = new LinkedHashMap<>(); 63 64 keyValueMap.entrySet().stream().forEach(entry -> { 65 if (specifyKey.equals(entry.getKey())) { 66 newKeyValueMap.put(targetKey, entry.getValue()); 67 } else { 68 newKeyValueMap.put(entry.getKey(), entry.getValue()); 69 } 70 }); 71 72 return newKeyValueMap; 73 } 74 }
结果:
方案1:
key:1, value:1
key:2, value:2
key:3, value:3
key:1_2, value:4
方案2:
key:1_1, value:1
key:2, value:2
key:3, value:3
key:1_2, value:4
结论:方案2的结果是我的期望,虽然方案1也可以同时保存数据,但是并不是我想要的。
也给我自己留一个TODO,方案1为什么不能成功,大家如果知道原因,也可以帮我解答下,至于此方案我觉得也非最优方案,如果有更优方案,也可分享给我和大家,谢谢各位!