集合
集合的体系
- 整个集合体系最大的就是单列集合Collection和双列集合(键值对)Map
- Collection接口下由两个子接口,分别为Set接口和List接口
- List系列集合:添加的元素是有序、可重复、有索引,例如ArrayList
- Set系列的集合:添加的元素是大部分无序、不重复、无索引
(一) 单列集合Collection
对于collection接口来说,其实现类能够使用的公共性方法
- add
- remove
- size
- contains
- iterator(包含hasNext和next,以及其自己的remove方法)
- forEach/增强For
集合的遍历:
- Iterator迭代器
特点:通过hasNext和next方法,来构建循环体系,hasNext表示是否有下一个,返回布尔值,next可以直接获取到下一个元素,返回拿到的元素,可以使用迭代器自己的remove方法,避免并发修改异常。
//用法
public static void main(String[] args) {
Collection coll = new ArrayList<String>();
coll.add("AAA");
coll.add("BBB");
coll.add("CCC");
coll.add("DDD");
Iterator<String> it =coll.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}//main
//此处解释以下为什么 Iterator<String> it =coll.iterator();
//迭代器本来就是方法,但我们需要用迭代器内的方法,对于接口想要用
//方法,只能用其实现类
- 增强for
缺点:因为底层是迭代器,所以在遍历时,不能使集合的方式对其进行增删,再加上没有迭代器对象,也无法删除 - forEach
缺点:因为其底层也是迭代器,所以增强for的缺点其也存在,再加上由于是匿名内部类, 访问外部类的局部变量的时候, 会被final修饰, 我们不能对其修改!!!
//此处的coll是一个集合
coll.forEach(new Consumer() {
@Override
public void accept(Object o) {
System.out.println(o);
}
});
coll.forEach(System.out::println);
coll.forEach(str -> System.out.println(str));
//使用lamada表达式简化
- 此处没有普通fori循环的原因就是,Collection还包含着Set,Set内的数据没有索引
- 并发修改异常(面试经典题目)
-
概念:因为我们在使用以迭代器为底层的循环体系时,使用集合的方法删除或增加元素,导致循环体系的索引迁移,cursor没有经过调整,导致了并发修改异常。
-
深层逻辑:使用了一个modCount的变量, 记录外部类集合增删的次数, 创建迭代器的时候会使用expectedModCount记录这个初始的modCount的值, 一旦我们采用外部类集合的增删方法, 就会导致modCount的值发生变化, 但是迭代器的expectedModCount的值没有变化, 而modCount的值和expectedModCount的值进行比较, 如果不相等, 就会报并发修改异常!!!
-
迭代器使用自己的remove方法,为什么就不会产生并发修改异常?
答:删除了元素, 回退了指针, 而且同步了modCount和expectedModCount的值。
1. List 接口
- LinkedList与ArrayList同属于List接口,而以下方法独属于List,且List的循环还需要包含普通fori,因为其都包含索引。
方法(涉及index) | 解释说明: |
---|