Java中ListE对象赋值问题(引用传递和值传递)
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对象赋值问题(引用传递和值传递)相关推荐
- Java中的对象类型像引用还是指针,谁是谁非?
Java中的对象类型像引用还是指针,谁是谁非? 作者:海枫 地址:http://blog.csdn.net/linyt 作为一名程序员,我们应该对新知识和新技术刨根问底,而不应泛泛而谈.我未曾接触到J ...
- Java中子类对象赋值给父类变量
1. 在Java中将一个字类对象赋值给父类变量是合法的,这也是实现多态(即方法的动态分派)的前提条件之一. 2. 在Java中父类赋值同样也适用于数组.可以将一个子类数组赋值给一个父类数组变量.但可能 ...
- java中HashSet对象内的元素的hashCode值不能变化
因为不管是HashMap(或HashTable,还是HashSet),key值是以hashCode值存进去的,加入key值变了,将无法从集合内删除对象,导致内存溢出. 转载于:https://www. ...
- java中的对象引用与c++中的对象赋值
1.java中的的对象引用与c++中的对象赋值比较 1.1在JAVA中用等号对类对象进行赋值,实际上操作的是对象的地址.等号左边的对象名是对象引用,右边可以是对象引用或者对象本身. eg: packa ...
- java中是引用传递还是值传递....
刚才与Z师兄聊天,他提问: 你说java中是引用传递还是值传递啊? 当时俺搞混了这个"传递"的意思, 本来以为是对象的实例化比如: abc a=new abc(); 这个a 是引用 ...
- java引用传递_理解Java中的引用传递和值传递
关于Java传参时是引用传递还是值传递,是一个讨论比较多的话题, 有说Java中只有值传递,也有些地方说引用传递和值传递都存在,本篇记录思考过程,不保证正确性, 感兴趣的同学一起讨论. 1.基本类型和 ...
- Java String 到底是引用传递还是值传递?
对于非对象类型,java 参数传递都是值传递, 比如int. java 会直接复制一份值到方法参数里面去使用. 而对于对象类型,其实也是值传递,java 参数传递值的是对象的引用,相当于对象在堆里面的 ...
- Java中,一切皆是对象——java中的对象类型与基本数据类型的区别
起因:取一个list给另一个list赋值,然后在另一个list中取出进行修改.list其中类型为对象时,String时,基本数据类型时. [java中的对象类型与基本数据类型的区别] #声明和实例化 ...
- java是引用传递还是值传递_流言终结者:Java是引用传递还是值传递?
前言 今天聊一个很小的话题,引用传递和值传递.为什么拉出这个话题呢?因为自己太菜吧-在这上边栽了跟头.所以今天就聊一聊Java中是引用传递还是值传递. 正文 小A:MDove,我有一个疑问:Java的 ...
最新文章
- “微信应用号对行业影响”之一,app开发速来围观
- Python+OpenCV实现自动扫雷,创造属于自己的世界记录!
- pureftpd + pureftp-user-manager 构建磁盘配额,速率限制,web管理ftpserver
- 这才是真正的Git——Git实用技巧
- excel列显示形式互换(字母与数字)
- 配置Tomcat的日志系统
- 将Auth0 OIDC(OAUTH 2)与授权(组和角色)集成
- 学会这二十个正则表达式,能让你少些1000行代码!
- python如何实现分布式_Python如何快速实现分布式任务
- 【2019南京ICPC网络赛 D】Robots【DAG上的随机游走】
- MPC5744P-时钟模块
- 软件工程实践: 敏捷开发流程图(scrum)
- hg8245c backupsettings.html,如何通过中国电信光猫华为HG8245C打开IPV6
- IDEA设置字体随鼠标滚动放大缩小
- 大自然Windows XP日文版镜像
- 模拟美式橄榄球比赛数据(R)
- 洪荒修真服务器名字可以修改吗,洪荒修真变态版
- 微信公众号网页分享功能开发
- wpf label下划线不显示的问题
- 保护环境的画用计算机怎么画,保护环境的画简笔画
热门文章
- Winforn中设置ZedGraph曲线图的属性、坐标轴属性、刻度属性
- Jquery中发送ajax请求示例代码
- Vue过滤器的简单使用--实时显示格式化的时间
- Vuex-全局状态集中式管理神器,做vue项目不知道Vuex真的out了
- 为鸿蒙说两句公道话,鸿蒙是安卓的套壳吗?
- 方法的定义使用,方法重载及方法的递归调用
- python limit_Python MySQL Limit
- python中csv库_关于python 自带csv库的使用心得 附带操作实例以及excel下乱码的解决...
- mysql starting server 失败_安装MySQL过程中(最后starting server)报错解决方案
- 神策数据:游戏买量与长线运营的数据宝典