我有以下代码:
private List<String> listOfStrings = new ArrayList<>();
listOfStrings.add("a");
listOfStrings.add("b");
listOfStrings.add("c");
listOfStrings.add("d");
for (String temp : listOfStrings) {
if (temp.equals("c")) {
Collections.swap(listOfStrings, 0, listOfStrings.indexOf(temp));
}
}这个列表可能不仅仅是字符串列表,还可以是我编写的类定义的对象列表。我不确定交换,我看到它编译和运行良好,但我不知道它在这里是否安全。
有人对此有什么建议吗?如果我需要交换的话。我计划使用for (int i = 0; i < size; i++)迭代并使用list.get(i)获取项,但我认为在数组列表中使用list.get(i)不是个好主意吗?
任何帮助都将不胜感激!提前谢谢!!
发布于 2016-04-25 06:43:57
如果您担心一个ConcurrentModificationException,是的,从循环中调用交换是安全的。
增强后的for循环将在内部使用迭代器,当迭代器本身检测到列表的结构修改时,迭代器可能会抛出一个ConcurrentModificationException。尽管确实修改了列表,但并不是在进行结构修改:结构修改是列表(或支持数组)大小发生变化的一种修改。仅仅设置一个值并不被认为是一种结构修改。来自Java API documentation
(结构修改是添加或删除一个或多个元素或显式调整支持数组大小的任何操作;仅设置元素的值并不是结构修改。)
但是,在您的情况下使用基于索引的for循环会更快。原因是indexOf(temp)调用实际上需要找到对象才能获得它的索引,所以它必须再次循环列表项。所以你的算法有二次运行时间。在基于索引的for-循环中,您已经知道要交换的元素的索引,因此这是不必要的,而且您有线性运行时间。
发布于 2016-04-25 07:29:21
我猜你的问题是‘我可以抛出一个ConcurrentModificationException__?'’
要回答这个问题,您应该知道何时以及为什么在集合中抛出ConcurrentModificationException。
以ArrayList为例:
ArrayList有一个字段modCount,意思是modification count。当调用一些导致ArrayList结构修改的方法(如add()/remove() )时,会增加modCount``(modCount++)。ArrayList.Iterator有一个字段expectedModCount,创建时由ArrayList的modCount分配。当调用next()或remove()时,将将expectedModCount与modCount进行比较,如果不等于,则会引发ConcurrentModificationException。Collections.swap的源代码:
公共静态空交换(List<?> list,int i,int j) {最终列表l= list;l.set(i,l.set(j,l.get(I);}
Collections.swap调用ArrayList的set()方法,该方法不会增加modCount,因此不会导致ConcurrentModificationException。https://stackoverflow.com/questions/36833111
复制相似问题