• 修改Map中确定key对应的value问题


    今天在码代码的时候出现一个没有预料的问题:

    先看下面的代码:

    public static void main(String[] args) {
    		String[] files=new String[]{"abcd","qwer","asdf"};
    		Map<String,Object> map=new HashMap<String,Object>();
    		map.put("file", "12345");
    		map.put("id", 15);
    		map.put("name", "works");
    		
    		List<Map<String,Object>> list=new ArrayList<Map<String,Object>>();
    		for (int i = 0; i < files.length; i++) {
    			list.add(map);
    			list.get(i).put("file", files[i]);
    		}
    		System.out.println(list.toString());		
    	}

    这里map模拟从数据库取到的一条记录,我的本意是根据files的大小生成一个包含n个map的List<Map<String,Object>,list中map的其他key的值都不变,只有key为file的值须要替换为files数组内的内容,于是大致写了上述的处理代码,咋一看上去没有任何问题。运行之后发现,list中的每一个map中key为file的value都为“asdf” !这是什么问题呢,换了多种方法处理,例如,先生成list,再遍历list进行修改,可是结果没有任何变化,超出预期!

    [{id=15, file=asdf, name=works}, {id=15, file=asdf, name=works}, {id=15, file=asdf, name=works}]

    折腾好久,终于发现问题:其实list中的所有元素(map)的引用都是指向内存中的同一块区域,所以上述的修改方式,最终会变成上述输出。

    处理办法:

    public static void main(String[] args) {
    		String[] files=new String[]{"abcd","qwer","asdf"};
    		Map<String,Object> map=new HashMap<String,Object>();
    		map.put("file", "12345");
    		map.put("id", 15);
    		map.put("name", "works");
    		
    		List<Map<String,Object>> list=new ArrayList<Map<String,Object>>();
    		for (int i = 0; i < files.length; i++) {
    			Map<String,Object> hmp=new HashMap<String,Object>();
    			Iterator<String> it=map.keySet().iterator();
    			while (it.hasNext()) {
    				String key = (String) it.next();
    				hmp.put(key, map.get(key));
    			}
    			list.add(hmp);
    			list.get(i).put("file", files[i]);
    		}
    		System.out.println(list.toString());		
    	}

    这样做的目的是每次都new一个Map对象hmp,然后把原来map中的内容复制到新的Map对象中,那么list中的map对象便是分别拥有不同的存储区域。然后对key对应的value进行修改时便不会出现之前被覆盖的问题了。

    [{id=15, file=abcd, name=works}, {id=15, file=qwer, name=works}, {id=15, file=asdf, name=works}]

    出现这个问题,主要是对内存/对象的引用以及Map的相关API理解不深导致

  • 相关阅读:
    8月7号的练习:HDU 1069&&POJ 1636&&HDU 1031&&HDU 1051&&HDU 1551
    8月8号的线段树:HDU 1754&&POJ 3264&&HDU1166
    8月6号的题目:HDU 1003&& POJ 1050&&HDU 1800&&HDU 2036&& POJ 1088(记忆化搜索)
    HDU 1052
    背包问题九讲:
    一个人的旅行 HDU 2066 &&HDU Today HDU 2112
    8月3号的LCS,LIS,LICS:Longest Ordered Subsequence&&Common Subsequence&&Greatest Common Increasing Subsequence
    那些操蛋的搜索题目:逃离迷宫&&哈密顿绕行世界问题
    C语言栈调用机制初探
    linux0.11改进之四 基于内核栈的进程切换
  • 原文地址:https://www.cnblogs.com/elgin-seth/p/5293777.html
Copyright © 2020-2023  润新知