- 浏览: 779388 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (360)
- Java (101)
- JPA/Hibernate (10)
- Spring (14)
- Flex/BlazeDS (37)
- Database (30)
- Lucene/Solr/Nutch (0)
- Maven/Ant (25)
- CXF/WebService (3)
- RPC/RMI/SOAP/WSDL (1)
- REST (6)
- TDD/BDD/JUnit (1)
- Servlet/JSP (2)
- AI/MachineLearning (3)
- Resource (1)
- 字符编码 (2)
- OOA/OOPS/UML (5)
- DesignPattern (8)
- 算法与数据结构 (11)
- Web&App Server (13)
- 并发&异步&无阻塞 (7)
- Entertainment (4)
- JavaScript/ExtJS (45)
- CodeStyle&Quality (1)
- svn/git/perforce (8)
- JSON (2)
- JavaScriptTesting (4)
- Others (6)
- RegularExpression (2)
- Linux/Windows (12)
- Protocal (2)
- Celebrities (1)
- Interview (1)
- 计算机语言 (1)
- English (2)
- Eclipse (5)
- TimeZone/时区 (1)
- Finance (1)
- 信息安全 (1)
- JMS/MQ (2)
- XSD/XML/DTD (3)
- Android (4)
- 投资 (3)
- Distribution (3)
- Excel (1)
最新评论
-
qdujunjie:
如果把m换成具体的数字,比如4或者5,会让读者更明白
m阶B树中“阶”的含义 -
java-admin:
不错,加油,多写点文章
关于Extjs的mixins和plugin -
xiehuaidong880827:
你好,我用sencha cmd打包完本地工程后,把app.js ...
ExtJS使用Sencha Cmd合并javascript文件为一个文件 -
KIWIFLY:
lwpan 写道inverse = "true&qu ...
Hibernate中什么时候使用inverse=true -
luedipiaofeng:
good
消除IE stop running this script弹出框
注意,这里的参考文章基本来自Effective Java和jdk源码
1)ConcurrentModificationException
当你用for each遍历一个list时,如果你在循环主体代码中修改list中的元素,将会得到这个Exception,解决的办法是:
1)用listIterator, 它支持在遍历的过程中修改元素,
2)不用listIterator, new一个新的list,copy old list content to new list, and then modify the new created list, in this way we can avoid such expception.
注意Collection中只有iterator,没有listIterator,List接口中才有listIterator.
请注意,listIterator的remove方法是不需要参数的,因为它是针对最近一次由next或previous获取的对象而言的.
void java.util.ListIterator.remove()
Removes from the list the last element that was returned by next or previous (optional operation). This call can only be made once per call to next or previous. It can be made only if ListIterator.add has not been called after the last call to next or previous.
事实上,不仅只有remove方法这样,ListIterator里面的add,set方法也是基于next和previous返回的结果的。详情可以参考jdk源代码。
扩展知识:
java.util.ConcurrentModificationException
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
java.util.ListIterator<E>
An iterator for lists that allows the programmer to traverse the list in either direction, modify the list during iteration, and obtain the iterator's current position in the list. A ListIterator has no current element; its cursor position always lies between the element that would be returned by a call to previous() and the element that would be returned by a call to next(). An iterator for a list of length n has n+1 possible cursor positions, as illustrated by the carets (^) below:
Element(0) ^ Element(1) ^ Element(2) ... Element(n-1)^cursor positions: ^
Note that the remove and set(Object) methods are not defined in terms of the cursor position; they are defined to operate on the last element returned by a call to next or previous().
This interface is a member of the Java Collections Framework.
2)关于clone以及Cloneable接口
Cloneable里面没有包含任何方法,它只是决定了Object中受保护的clone方法实现的行为:如果一个类实现了Cloneable, Object的clone方法就返回该对象的逐域拷贝,否则就抛出CloneNotSupportedException。这是接口的一种极端非典型的用法,不值得效仿。通常情况下,实现接口是为了表明类可以为它的客户做些什么。然而对应Cloneable接口,它改变了超类中受保护的方法的行为。
Best Practise:
1)最好不要去实现自己的clone方法,即不要去implement Cloneable接口,要想拷贝,自己可以写一个copy方法,所有的内容完全由自己控制。
2)如果一定要实现Cloneable,那么首先通过super.clone()获取到最初始的拷贝对象,然后去覆盖一些域,因为对list而言,通过super.clone()方法获得的拷贝对象只是在栈中新建了一个list引用变量,但是这个引用变量还是指向原来list中的成员的,即并没有在堆中新建list的成员。
先看一下Jdk1.6 中HashMap的clone方法源码:
java.lang.Cloneable
A class implements the Cloneable interface to indicate to the java.lang.Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.
Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.
By convention, classes that implement this interface should override Object.clone (which is protected) with a public method. See java.lang.Object.clone() for details on overriding this method.
Note that this interface does not contain the clone method. Therefore, it is not possible to clone an object merely by virtue of the fact that it implements this interface. Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.
3)Collections.copy
按如上方式用时,很容易得到"Source does not fit in dest" Exception,原因是copy方法里面会首先比较dest和src的size,而往往你新new的list的size是0,所以会报错。
为什么明明已经设置了长度为src.size,为什么还会出错!
后来打印出dest.size()才知道dest的长度为0,new ArrayList<Object>(src.size())表示的是这个List的容纳能力为src.size,并不是说dest中就有了src.size个元素。查看api才知 道,它的capacity(容纳能力大小)可以指定(最好指定)。而初始化时size的大小永远默认为0,只有在进行add和remove等相关操作 时,size的大小才变化。然而进行copy()时候,首先做的是将desc1的size和src1的size大小进行比较,只有当desc1的 size 大于或者等于src1的size时才进行拷贝,否则抛出IndexOutOfBoundsException异常。
可以通过下面的方法指定目标desc的大小
执行第一句后,desc 的size的大小是为srcList的size,其实它是对一个空数组的浅拷贝,虽然是一个Object类型的空数组,但是list里面只存储引用变量,所以list的size已经变化了,只是每个引用变量还没有指向具体的对象而已。
Collections.copy源码
4)Collections.copy() versus ArrayList(Collection<? extends E> c)
两者都是浅拷贝,只是对源list的元素进行拷贝,拷贝的只是引用。拷贝后两个list的元素(引用)不同,但是引用所指向的对象是一样的。即两个list的每个元素指向的还是同一内存。
you are right, 都是浅拷贝.
1)ConcurrentModificationException
当你用for each遍历一个list时,如果你在循环主体代码中修改list中的元素,将会得到这个Exception,解决的办法是:
1)用listIterator, 它支持在遍历的过程中修改元素,
2)不用listIterator, new一个新的list,copy old list content to new list, and then modify the new created list, in this way we can avoid such expception.
注意Collection中只有iterator,没有listIterator,List接口中才有listIterator.
ListIterator<FilterCriteriaVO> listIterator=filterVOs.listIterator(); int size=filterVOs.size(); for (int i=0; i<size; i++) { FilterCriteriaVO filterExpression=listIterator.next(); listIterator.remove(); listIterator.add(leg1TypeExpression); }
请注意,listIterator的remove方法是不需要参数的,因为它是针对最近一次由next或previous获取的对象而言的.
void java.util.ListIterator.remove()
Removes from the list the last element that was returned by next or previous (optional operation). This call can only be made once per call to next or previous. It can be made only if ListIterator.add has not been called after the last call to next or previous.
事实上,不仅只有remove方法这样,ListIterator里面的add,set方法也是基于next和previous返回的结果的。详情可以参考jdk源代码。
扩展知识:
java.util.ConcurrentModificationException
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
java.util.ListIterator<E>
An iterator for lists that allows the programmer to traverse the list in either direction, modify the list during iteration, and obtain the iterator's current position in the list. A ListIterator has no current element; its cursor position always lies between the element that would be returned by a call to previous() and the element that would be returned by a call to next(). An iterator for a list of length n has n+1 possible cursor positions, as illustrated by the carets (^) below:
Element(0) ^ Element(1) ^ Element(2) ... Element(n-1)^cursor positions: ^
Note that the remove and set(Object) methods are not defined in terms of the cursor position; they are defined to operate on the last element returned by a call to next or previous().
This interface is a member of the Java Collections Framework.
2)关于clone以及Cloneable接口
Cloneable里面没有包含任何方法,它只是决定了Object中受保护的clone方法实现的行为:如果一个类实现了Cloneable, Object的clone方法就返回该对象的逐域拷贝,否则就抛出CloneNotSupportedException。这是接口的一种极端非典型的用法,不值得效仿。通常情况下,实现接口是为了表明类可以为它的客户做些什么。然而对应Cloneable接口,它改变了超类中受保护的方法的行为。
Best Practise:
1)最好不要去实现自己的clone方法,即不要去implement Cloneable接口,要想拷贝,自己可以写一个copy方法,所有的内容完全由自己控制。
2)如果一定要实现Cloneable,那么首先通过super.clone()获取到最初始的拷贝对象,然后去覆盖一些域,因为对list而言,通过super.clone()方法获得的拷贝对象只是在栈中新建了一个list引用变量,但是这个引用变量还是指向原来list中的成员的,即并没有在堆中新建list的成员。
先看一下Jdk1.6 中HashMap的clone方法源码:
/** * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and * values themselves are not cloned. * * @return a shallow copy of this map */ public Object clone() { HashMap<K,V> result = null; try { result = (HashMap<K,V>)super.clone(); } catch (CloneNotSupportedException e) { // assert false; } result.table = new Entry[table.length]; result.entrySet = null; result.modCount = 0; result.size = 0; result.init(); result.putAllForCreate(this); return result; }
java.lang.Cloneable
A class implements the Cloneable interface to indicate to the java.lang.Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.
Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.
By convention, classes that implement this interface should override Object.clone (which is protected) with a public method. See java.lang.Object.clone() for details on overriding this method.
Note that this interface does not contain the clone method. Therefore, it is not possible to clone an object merely by virtue of the fact that it implements this interface. Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.
3)Collections.copy
List<Object> dest=new ArrayList<Object>(src.size()); //or List<Object> dest=new ArrayList<Object>(); Collections.copy(dest, src());
按如上方式用时,很容易得到"Source does not fit in dest" Exception,原因是copy方法里面会首先比较dest和src的size,而往往你新new的list的size是0,所以会报错。
为什么明明已经设置了长度为src.size,为什么还会出错!
后来打印出dest.size()才知道dest的长度为0,new ArrayList<Object>(src.size())表示的是这个List的容纳能力为src.size,并不是说dest中就有了src.size个元素。查看api才知 道,它的capacity(容纳能力大小)可以指定(最好指定)。而初始化时size的大小永远默认为0,只有在进行add和remove等相关操作 时,size的大小才变化。然而进行copy()时候,首先做的是将desc1的size和src1的size大小进行比较,只有当desc1的 size 大于或者等于src1的size时才进行拷贝,否则抛出IndexOutOfBoundsException异常。
可以通过下面的方法指定目标desc的大小
List<Object> values=new ArrayList<Object>(Arrays.asList(new Object[srcList.size()])); Collections.copy(values, srcList());
执行第一句后,desc 的size的大小是为srcList的size,其实它是对一个空数组的浅拷贝,虽然是一个Object类型的空数组,但是list里面只存储引用变量,所以list的size已经变化了,只是每个引用变量还没有指向具体的对象而已。
Collections.copy源码
/** * Copies all of the elements from one list into another. After the * operation, the index of each copied element in the destination list * will be identical to its index in the source list. The destination * list must be at least as long as the source list. If it is longer, the * remaining elements in the destination list are unaffected. <p> * * This method runs in linear time. * * @param dest The destination list. * @param src The source list. * @throws IndexOutOfBoundsException if the destination list is too small * to contain the entire source List. * @throws UnsupportedOperationException if the destination list's * list-iterator does not support the <tt>set</tt> operation. */ public static <T> void copy(List<? super T> dest, List<? extends T> src) { int srcSize = src.size(); if (srcSize > dest.size()) throw new IndexOutOfBoundsException("Source does not fit in dest"); if (srcSize < COPY_THRESHOLD || (src instanceof RandomAccess && dest instanceof RandomAccess)) { for (int i=0; i<srcSize; i++) dest.set(i, src.get(i)); } else { ListIterator<? super T> di=dest.listIterator(); ListIterator<? extends T> si=src.listIterator(); for (int i=0; i<srcSize; i++) { di.next(); di.set(si.next()); } } }
4)Collections.copy() versus ArrayList(Collection<? extends E> c)
两者都是浅拷贝,只是对源list的元素进行拷贝,拷贝的只是引用。拷贝后两个list的元素(引用)不同,但是引用所指向的对象是一样的。即两个list的每个元素指向的还是同一内存。
评论
2 楼
darrenzhu
2014-05-30
Checkmate 写道
最后一条我倒是看到了不同的解释.
Both methods are shallow copy. So what is the difference between these two methods?
First, Collections.copy() won’t reallocate the capacity of dstList even if dstList does not have enough space to contain all srcList elements. Instead, it will throw an IndexOutOfBoundsException. One may question if there is any benefit of it. One reason is that it guarantees the method runs in linear time. Also it makes suitable when you would like to reuse arrays rather than allocate new memory in the constructor of ArrayList.
Collections.copy() can only accept List as both source and destination, while ArrayList accepts
我也觉得貌似都是浅克隆.
Both methods are shallow copy. So what is the difference between these two methods?
First, Collections.copy() won’t reallocate the capacity of dstList even if dstList does not have enough space to contain all srcList elements. Instead, it will throw an IndexOutOfBoundsException. One may question if there is any benefit of it. One reason is that it guarantees the method runs in linear time. Also it makes suitable when you would like to reuse arrays rather than allocate new memory in the constructor of ArrayList.
Collections.copy() can only accept List as both source and destination, while ArrayList accepts
我也觉得貌似都是浅克隆.
you are right, 都是浅拷贝.
1 楼
Checkmate
2013-09-26
最后一条我倒是看到了不同的解释.
Both methods are shallow copy. So what is the difference between these two methods?
First, Collections.copy() won’t reallocate the capacity of dstList even if dstList does not have enough space to contain all srcList elements. Instead, it will throw an IndexOutOfBoundsException. One may question if there is any benefit of it. One reason is that it guarantees the method runs in linear time. Also it makes suitable when you would like to reuse arrays rather than allocate new memory in the constructor of ArrayList.
Collections.copy() can only accept List as both source and destination, while ArrayList accepts
我也觉得貌似都是浅克隆.
Both methods are shallow copy. So what is the difference between these two methods?
First, Collections.copy() won’t reallocate the capacity of dstList even if dstList does not have enough space to contain all srcList elements. Instead, it will throw an IndexOutOfBoundsException. One may question if there is any benefit of it. One reason is that it guarantees the method runs in linear time. Also it makes suitable when you would like to reuse arrays rather than allocate new memory in the constructor of ArrayList.
Collections.copy() can only accept List as both source and destination, while ArrayList accepts
我也觉得貌似都是浅克隆.
发表评论
-
sapjco3 notes
2019-03-21 14:51 1080sapjco https://support.sap.com/ ... -
使用RestTemplate发送post JSON请求
2019-01-12 17:30 4549private final String BASE_URL = ... -
使用RestTemplate发送post JSON请求
2019-01-12 17:30 3377private final String BASE_URL = ... -
Spring线程池ThreadPoolTaskExecutor
2018-08-06 09:51 1772<!-- spring thread pool ex ... -
Spring注解事物@Transactional不工作
2018-08-02 18:50 2514“In proxy mode (which is the de ... -
创建前缀索引报长度超出错误
2018-07-25 15:44 1637表结构定义如下: CREATE TABLE `sku` ( ` ... -
Mysql Varchar字符长度
2018-07-25 15:23 1287`sku_name` VARCHAR(200) NOT NUL ... -
使用 Spring RestTemplate 发送 post 请求
2018-07-23 18:49 11615注意点: 1)使用MultiValueMap设置入参,不要使 ... -
Java动态代理Dynamic Proxy
2018-07-21 16:33 720JAVA学习篇--静态代理VS动态代理 https://blo ... -
分布式实时日志分析解决方案 ELK 部署架构
2018-07-20 09:52 1136原文链接:http://www.importn ... -
为什么HashMap容量一定要为2的幂呢?
2018-07-19 10:07 1646原文链接:https://blog.csdn.net/wang ... -
为什么计算HashCode时通常选择31这个数?
2018-07-19 10:05 1321摘自http://www.importnew.com/2208 ... -
jackson自定义序列化和反序列化
2018-07-10 18:47 2166原文链接:https://blog.csdn.net/liu ... -
Pay special attention when modifying online running system
2017-06-23 10:25 0Never remove any properties, me ... -
Map中的Null key, Null Value
2017-06-14 10:52 1876ConcurrentHashMap的key和value都不能为 ... -
Java语法糖
2017-06-05 20:03 469Java语法糖之foreach http://www.imp ... -
Java集合相关
2017-05-24 17:55 0Java集合框架:ArrayList http://www. ... -
Java数据类型的转换:隐式(自动)转换与强制转换
2017-05-14 10:46 0http://blog.csdn.net/u011240877 ... -
分布式开放消息系统(RocketMQ)的原理与实践
2017-05-07 19:55 664分布式开放消息系统(RocketMQ)的原理与实践 http ... -
面试知识点复习(Interview knowledge review)
2017-05-07 18:39 0JVM,多线程相关知识 http://darrenzhu.it ...
相关推荐
java.util.ConcurrentModificationException 异常问题详解1
java.util.ConcurrentModificationException 解决方法 在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除。 则使用会报以下异常: Java.util....
Spring数据mongodb测试 在Collections.synchronizedList或Collections.synchronizedSet上测试spring数据mongodb ConcurrentModificationException
主要介绍了出现java.util.ConcurrentModificationException 问题及解决办法的相关资料,需要的朋友可以参考下
axis1.4补丁包,解决jdk1.8高并发报ConcurrentModificationException问题,该jar包重新编译jar包的一个class文件,线上环境通过
iterator和listIterator方法是快速失败的 :如果列表在任何时间从结构上修改创建迭代器之后,以任何方式,除了通过迭代器自身的remove或add方法,迭代器都将抛出ConcurrentModificationException 。 因此,在并发的...
如果没有这样的对象存在,列表应该使用Collections.synchronizedList方法“包装”。 这最好在创建时完成,以防止意外的不同步访问列表: List list = Collections.synchronizedList(new ArrayList(...)); The ...
3. 迭代过程中,即使Map结构被修改,也不会抛ConcurrentModificationException异常; 4. 除了数组+链表+红黑树的基本结构外,新增了转移节点,是为了保证扩容时的线程安全的节点; 5. 提供了很多Stream流式方法,...
今天小编就为大家分享一篇关于Java源码解析ArrayList及ConcurrentModificationException,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
NULL 博文链接:https://chenlinbo.iteye.com/blog/832335
Map在遍历时候通常 现获得其键值的集合Set,然后用迭代器Iterator来对Map进行遍历。
java.util.ConcurrentModificationException: mutation occurred during iteration [error] scala.collection.mutable.MutationTracker$.checkMutations(MutationTracker.scala:43) [error] scala.collection....
axis1.4 spring3.0 集成 实现 web service 服务端, axis1.4 客户端认证,授权,访问日志记录,集成spring 解决 PHP 调用web service 无法认证,和解析soap 模板
fastJson的全部资料,包括源码、开发需要用到的jar包和html格式的文档。
这里面包含了大部分的软件测试的专业术语,希望对你有用
Axis1.4快速发布服务以及客服端详解(资源中的axis是axis1.4自带的,lib也是它自带的)
Iterator遍历中 ConcurrentModificationException异常
3、在使用 project.tasks.withType()时,Gradle 4.8 有时会失败,并抛出 ConcurrentModificationException 。 4、依赖关系解析引擎有时会抛出 “Unexpected parent dependency” 报错,这在 Gradle 4.8 中变得更加...