目录
Collection集合的总结
1、如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?
- 用ArrayList集合(有序、可重复、有索引),底层基于数组的。(常用)
2、如果希望记住元素的添加顺序,且增删首尾数据的情况较多?
- 用LinkedList集合(有序、可重复、有索引l),底层基于双链表实现的。
3、如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快?
- 用HashSet集合(无序,不重复,无索引),底层基于哈希表实现的。(常用)
4、如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快?
- 用LinkedHashSet集合(有序,不重复,无索引),底层基于哈希表和双链表。
5、如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?
- 用TreeSet集合,基于红黑树实现。
集合的并发修改异常问题
- 使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误。
案例引入
通过一个小案例引入:
完成一个需求,找出集合中全部带“李”的名字,并从集合中删除。
使用迭代器实现
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("王麻子");
list.add("小李子");
list.add("李爱花");
list.add("张全蛋");
list.add("晓李");
list.add("李玉强");
System.out.println(list);
//需求:找出集合中全部带"李"的名字,并从集合中删除
Iterator<String> it = list.iterator();
while(it.hasNext()){
String name = it.next();
if(name.contains("李")){
list.remove(name);
}
}
System.out.println(list);
}
}
运行结果:

使用for循环实现
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("王麻子");
list.add("小李子");
list.add("李爱花");
list.add("张全蛋");
list.add("晓李");
list.add("李玉强");
System.out.println(list);
//需求:找出集合中全部带"李"的名字,并从集合中删除
for(int i = 0;i < list.size();i++){
String name = list.get(i);
if(name.contains("李")){
list.remove(name);
}
}
System.out.println(list);
}
}
使用for循环来实现,每次遇到带“李” 的名字,删除之后索引++,会跳过一个元素的检查,极大概率导致漏删。
运行结果:

for循环-解决方法
每次检索到带“李”的名字,就把i再减一,使索引回到正确的位置;或者从后往前进行检索和删除。
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("王麻子");
list.add("小李子");
list.add("李爱花");
list.add("张全蛋");
list.add("晓李");
list.add("李玉强");
System.out.println(list);
//需求:找出集合中全部带"李"的名字,并从集合中删除
for(int i = 0;i < list.size();i++){
String name = list.get(i);
if(name.contains("李")){
list.remove(name);
i--;
}
}
//或者倒着进行删除
System.out.println(list);
}
}
运行结果:

迭代器-解决方法
迭代器的解决方法就比较直接,我们在删除的时候就使用迭代器自己的删除方法就可以了:
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("王麻子");
list.add("小李子");
list.add("李爱花");
list.add("张全蛋");
list.add("晓李");
list.add("李玉强");
System.out.println(list);
//需求:找出集合中全部带"李"的名字,并从集合中删除
Iterator<String> it = list.iterator();
while(it.hasNext()){
String name = it.next();
if(name.contains("李")){
it.remove(); //删除迭代器当前遍历到的数据,每删除一个数据后,相当于也在底层做了i--
}
}
System.out.println(list);
}
}
运行结果也同样是:

注意:用增强for循环(foreach)遍历集合并删除数据,没有办法解决bug;同样,Lambda表达式也无法解决,因为其源代码也是使用foreach遍历的。
小结
- 由于增强for循环遍历集合就是迭代器遍历集合的简化写法,因此,使用增强for循环遍历集合,又在同时删除集合中的数据时,程序也会出现并发修改异常的错误。
怎么保证遍历集合同时删除数据时不出bug?
- 使用迭代器遍历集合,但用迭代器自己的删除方法删除数据即可。
- 如果能用for循环遍历时:可以倒着遍历并删除;或者从前往后遍历,但删除元素后做i--操作。
END
学习自:黑马程序员——JavaSE课程
1万+

被折叠的 条评论
为什么被折叠?



