Java中List<E>对象赋值操作问题

业务需求是:取2个集合中的交集对象并返回。如下代码,busMap中key值和stocks中Map中的key值相等的对象则返回继续操作,也就是说剔除stocks中的不存在于busMap中的对象,就是一个过滤操作。

实现代码 ① bug版
报错:
java.util.ConcurrentModificationException ; at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) ; at java.util.ArrayList$Itr.next(ArrayList.java:831) ;
原因:
forEach实现是采用Iterator实现的,而remove操作不能在Iterator下操作,所以报错,具体原因是Iterator遍历开始前,会对该对象生成一个改变前的标记值,在进行map.remove操作的时候,改变了这个值,导致循环结束后,程序检查初始标记和结束标记不一致,就报错了。而使用Iterator.remove操作时,它同时会修改这个初始标记值,一直让这个初始标记值等于当前标记值,程序结束后判断两者相等,就不会有异常!

private static void  appendStock(Map<String,Object> busMap, List<Map<String, Object>> stocks , String key){if (stocks != null)for (Map<String,Object> s : stocks ) {boolean b = false;for (Map.Entry<String, Object> e : busMap.entrySet()) {if (s.get("stock_code") != null)if (s.get("stock_code").toString().equals(e.getKey())) {b = true;break;}}if ( !b ){stocks.remove(s);}}
}

代码② 修正foreach中remove异常,bug版
bug:
执行该方法后,stocks并没有改变!!
原因:
对象引用传递导致。这个stocks是形参,他会复制外界的引用,也就是说这个stocks和外界的stocks不是同一个引用,但是指向同一个内存地址。所以只要stocks指向的对象修改了,外界对象(同一个对象)也随着修改。但是这个stocks是形参,是一个新的变量,生命周期只存在于该方法体内,所以代码最后stocks = newStocks没有任何意义,因为调用方法结束,newStocks和stocks都会被GC干掉,外界对象引用地址是没有发生一点变化的。唯独变化的就是外界对象的另一个引用(就是方法中的stocks)在方法中对其的修改!这就告诉我们一个道理:在设计方法是void还是return的时候,要看看外界引用是否需要被重新赋值。如果需要,则return,否则void。也就是void方法只是对外界对象的堆内存操作。return对象多了可以对外界对象引用的修改优势,但是这要加大开销!

private static void  appendStock(Map<String,Object> busMap, List<Map<String, Object>> stocks , String key){if (stocks != null)List<Map<String,Object>> newStocks =  Lists.newArrayList();  // 构建新对象保存交集数据for (Map<String,Object> s : stocks ) {for (Map.Entry<String, Object> e : busMap.entrySet()) {if (s.get("stock_code") != null)if (s.get("stock_code").toString().equals(e.getKey())) {newstocks.add(s);break;}}}stocks = newStocks;
}

代码③ 绕开改变外界引用,稳定版
采用Iterator来删除元素,摒弃拷贝,从而不入浅拷贝的坑

private static void  appendStock(Map<String,Object> busMap, List<Map<String, Object>> stocks , String key){if (stocks != null && stocks.size() > 0) {Iterator<Map<String, Object>> iterator = stocks.iterator();while (iterator.hasNext()) {Map<String, Object> s = iterator.next();if (s.get("stock_code") != null) {String stockCode = String.valueOf(s.get("stock_code"));if ( !busMap.containsKey(stockCode)) {iterator.remove();}}}}
}

代码④返回引用赋值给外界引用,稳定版

    private static List<Map<String, Object>>  appendStock(Map<String,Object> busMap, List<Map<String, Object>> stocks , String key){if (stocks != null)List<Map<String,Object>> newStocks =  Lists.newArrayList();  // 构建新对象保存交集数据for (Map<String,Object> s : stocks ) {for (Map.Entry<String, Object> e : busMap.entrySet()) {if (s.get("stock_code") != null)if (s.get("stock_code").toString().equals(e.getKey())) {newstocks.add(s);break;}}}return newStocks;
}

转载于:https://blog.51cto.com/11939788/2162805

Java中ListE对象赋值问题(引用传递和值传递)相关推荐

  1. Java中的对象类型像引用还是指针,谁是谁非?

    Java中的对象类型像引用还是指针,谁是谁非? 作者:海枫 地址:http://blog.csdn.net/linyt 作为一名程序员,我们应该对新知识和新技术刨根问底,而不应泛泛而谈.我未曾接触到J ...

  2. Java中子类对象赋值给父类变量

    1. 在Java中将一个字类对象赋值给父类变量是合法的,这也是实现多态(即方法的动态分派)的前提条件之一. 2. 在Java中父类赋值同样也适用于数组.可以将一个子类数组赋值给一个父类数组变量.但可能 ...

  3. java中HashSet对象内的元素的hashCode值不能变化

    因为不管是HashMap(或HashTable,还是HashSet),key值是以hashCode值存进去的,加入key值变了,将无法从集合内删除对象,导致内存溢出. 转载于:https://www. ...

  4. java中的对象引用与c++中的对象赋值

    1.java中的的对象引用与c++中的对象赋值比较 1.1在JAVA中用等号对类对象进行赋值,实际上操作的是对象的地址.等号左边的对象名是对象引用,右边可以是对象引用或者对象本身. eg: packa ...

  5. java中是引用传递还是值传递....

    刚才与Z师兄聊天,他提问: 你说java中是引用传递还是值传递啊? 当时俺搞混了这个"传递"的意思, 本来以为是对象的实例化比如: abc a=new abc(); 这个a 是引用 ...

  6. java引用传递_理解Java中的引用传递和值传递

    关于Java传参时是引用传递还是值传递,是一个讨论比较多的话题, 有说Java中只有值传递,也有些地方说引用传递和值传递都存在,本篇记录思考过程,不保证正确性, 感兴趣的同学一起讨论. 1.基本类型和 ...

  7. Java String 到底是引用传递还是值传递?

    对于非对象类型,java 参数传递都是值传递, 比如int. java 会直接复制一份值到方法参数里面去使用. 而对于对象类型,其实也是值传递,java 参数传递值的是对象的引用,相当于对象在堆里面的 ...

  8. Java中,一切皆是对象——java中的对象类型与基本数据类型的区别

    起因:取一个list给另一个list赋值,然后在另一个list中取出进行修改.list其中类型为对象时,String时,基本数据类型时. [java中的对象类型与基本数据类型的区别] #声明和实例化 ...

  9. java是引用传递还是值传递_流言终结者:Java是引用传递还是值传递?

    前言 今天聊一个很小的话题,引用传递和值传递.为什么拉出这个话题呢?因为自己太菜吧-在这上边栽了跟头.所以今天就聊一聊Java中是引用传递还是值传递. 正文 小A:MDove,我有一个疑问:Java的 ...

最新文章

  1. “微信应用号对行业影响”之一,app开发速来围观
  2. Python+OpenCV实现自动扫雷,创造属于自己的世界记录!
  3. pureftpd + pureftp-user-manager 构建磁盘配额,速率限制,web管理ftpserver
  4. 这才是真正的Git——Git实用技巧
  5. excel列显示形式互换(字母与数字)
  6. 配置Tomcat的日志系统
  7. 将Auth0 OIDC(OAUTH 2)与授权(组和角色)集成
  8. 学会这二十个正则表达式,能让你少些1000行代码!
  9. python如何实现分布式_Python如何快速实现分布式任务
  10. 【2019南京ICPC网络赛 D】Robots【DAG上的随机游走】
  11. MPC5744P-时钟模块
  12. 软件工程实践: 敏捷开发流程图(scrum)
  13. hg8245c backupsettings.html,如何通过中国电信光猫华为HG8245C打开IPV6
  14. IDEA设置字体随鼠标滚动放大缩小
  15. 大自然Windows XP日文版镜像
  16. 模拟美式橄榄球比赛数据(R)
  17. 洪荒修真服务器名字可以修改吗,洪荒修真变态版
  18. 微信公众号网页分享功能开发
  19. wpf label下划线不显示的问题
  20. 保护环境的画用计算机怎么画,保护环境的画简笔画

热门文章

  1. Winforn中设置ZedGraph曲线图的属性、坐标轴属性、刻度属性
  2. Jquery中发送ajax请求示例代码
  3. Vue过滤器的简单使用--实时显示格式化的时间
  4. Vuex-全局状态集中式管理神器,做vue项目不知道Vuex真的out了
  5. 为鸿蒙说两句公道话,鸿蒙是安卓的套壳吗?
  6. 方法的定义使用,方法重载及方法的递归调用
  7. python limit_Python MySQL Limit
  8. python中csv库_关于python 自带csv库的使用心得 附带操作实例以及excel下乱码的解决...
  9. mysql starting server 失败_安装MySQL过程中(最后starting server)报错解决方案
  10. 神策数据:游戏买量与长线运营的数据宝典