zoukankan      html  css  js  c++  java
  • Java开发中碰到的Map的坑

    这属于我在开发中碰过的坑 ,容器中存放者对象,当clear()的时候,出现的奇葩问题。好了,直接看代码:

    package com.DataType.yinyong;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class TestMethod {
        //我总结了一下,因为实际开发中涉及到代码层级较深,所以有时候会不容易看出问题
        public static void main(String[] args) {
            TestMethod testMethod =new TestMethod();
            List<Map<String, List<Object>>> resultMaps = new ArrayList<Map<String, List<Object>>>();
            resultMaps.add(testMethod.getList());
            testMethod.testXunHuan(resultMaps);
            
        }
    
        public void testXunHuan(List<Map<String, List<Object>>> resultMaps) {
            for (Map<String, List<Object>> resultMap : resultMaps) {
                int resultNum = 0;
                List<Object> result = resultMap.get("r1");
                resultMap.remove("r1");
                if (result == null)
                    continue;
                resultNum = result.size();
                if (resultNum <= 0) {
                    continue;
                }
                for (int i = 0; i < result.size(); i++) {
                    Object o = result.get(i);
                }
                result.clear();
                System.out.println("虽然 我修改的result是指向r1,但是我的map内的另外一个值 :"+resultMap.get("r12"));
            }
        }
    
        public Map<String, List<Object>> getList() {
            Map<String, List<Object>> resultMap = new HashMap<String, List<Object>>();
            //下面我提供一个List<Object>,并且让resultMap中不同的key引用相同的值
            Map<String, List<Object>> srcMap = new HashMap<String, List<Object>>();
            List<Object> srcList = new ArrayList<Object>();
            for(int i = 0 ; i < 10;i++){
                srcList.add("count");
            }
            srcMap.put("key1", srcList);
            srcMap.put("key2", srcList);
            //下面我声明一个新的list用来
            List<Object> result = srcMap.get("key1");
            resultMap.put("r1", result);
            List<Object> result2 = srcMap.get("key2");
            resultMap.put("r12", result2);
            System.out.println("resul实际上是一个"+(result ==result2) );
            return resultMap;
        }
        
    }

     输出结果:

    总结 :

      1,java中是弱化了引用还是传值的概念,也不需要考虑指针。

        2, 但有些时候,特别是容器内还是需要注意一下,有可能Map中两个key指向的value是同一个对象,这时候,当你选择拿到一个值 clear(),就会出现错误

      3, 于是你可以采用两种方式解决这一问题

         ① :如果不去clear(),的确不会对其他数据产生影响,但是会造成内存消耗大,实际开发不可取(实际开发中不可能只有这两个键值对)

         ② :可以选择copy一下数组,但是同样的原因导致不可取(注意collections.copy()方法是如何使用的

    public Map<String, List<Object>> getList() {
            Map<String, List<Object>> resultMap = new HashMap<String, List<Object>>();
            //下面我提供一个List<Object>,并且让resultMap中不同的key引用相同的值
            Map<String, List<Object>> srcMap = new HashMap<String, List<Object>>();
            List<Object> srcList = new ArrayList<Object>();
            for(int i = 0 ; i < 10;i++){
                srcList.add("count");
            }
            List<Object> srcList1 = new ArrayList<Object>();
            Collections.addAll(srcList1,  new  Object[srcList.size()]); 
            Collections.copy(srcList1, srcList);//collection.copy(dest,src)方法需要dest的size大于等于src、属于深copy
            srcMap.put("key1", srcList);
            srcMap.put("key2", srcList1);
            //下面我声明一个新的list用来
            List<Object> result = srcMap.get("key1");
            resultMap.put("r1", result);
            List<Object> result2 = srcMap.get("key2");
            resultMap.put("r12", result2);
            System.out.println("resul实际上是一个List么"+(result ==result2) );
            return resultMap;
        }

      4;最终我决定,每次clear之前,先去判断是否存在有其他key用到

    public void testXunHuan(List<Map<String, List<Object>>> resultMaps) {
            for (Map<String, List<Object>> resultMap : resultMaps) {
                int resultNum = 0;
                List<Object> result = resultMap.get("r1");
                resultMap.remove("r1");
                if (result == null)
                    continue;
                resultNum = result.size();
                if (resultNum <= 0) {
                    continue;
                }
                for (int i = 0; i < result.size(); i++) {
                    Object o = result.get(i);
                }
                boolean isExistSame =false;
                Iterator< List<Object>>  ite= resultMap.values().iterator();
                while(ite.hasNext()){
                    if(ite.next().equals(result)){
                        isExistSame = true;
                        break;
                    }
                }
                //只有不存在相同值,才可以删除
                if(!isExistSame){
                    result.clear();
                }
                System.out.println("虽然 我修改的result是指向r1,但是我的map内的另外一个值 :"+resultMap.get("r12"));
            }
        }

    参考:

    由java中深度复制一伸出Collections.copy的使用

    Java中的深拷贝(深复制)和浅拷贝(浅复制)

    渐析java的浅拷贝和深拷贝

        

  • 相关阅读:
    Linux下修改IP
    Linux 常用操作
    flex addChild 的一个小细节
    類別 ConcurrentHashMap<K,V>的更新,删除
    游戏开发者的AS3数据结构 COOL!
    Adobe Flash gets its full launch on Android
    人生时间表. 如果您有了时间
    Flex数据绑定陷阱:常见的误用和错误(一) 闪吧教材.jpg
    flash player10 Vector类型
    如何使用Flex 4新的CSS语法,兼容halo组件
  • 原文地址:https://www.cnblogs.com/ldh-better/p/7172014.html
Copyright © 2011-2022 走看看