list一个简单介绍:
List是一个接口,主要实现类有两个LinkedList,ArrayList,两者在底层实现上有差异,LinkedList底层采用的是链表存储,ArrayList底层采用的是数组存储。
List的特征:元素有序,可重复。
查找:
根据list下标查找元素: list.get(index)
根据元素查找第一次出现的位置 :list.indexOf(obj)
判断元素是否存在:list.contains(obj)
排序:
list本身是有序的集合,按照元素插入顺序排序的。
如果要按照其他顺序排序的话,这么做:
1,待排序元素类实现Comparable接口,重写compareTo方法。
2,Collections.sort(list);,对已经添加完成的list进行排序。
删除:
1,下标方式删除:
list.remove(index)
2,指定元素删除
list.remove(obj)
在循环中删除元素可以不?
list遍历元素的方式有3:
1,for遍历的方式:循环中可以删除元素
for (int i = 0; i < list.size(); i++) {
list.remove(i);
}
2,foreach遍历的方式:
底层是基于迭代器实现的,所以遍历过程中也是不能使用集合对象去操作元素的。
3,Iterator遍历方式:循环中不可以删除元素
list.Iterator()创建一个迭代器,迭代期间,如果修改list(add,remove),在获取next的时候,首先进行checkForComodification检查当前list是否做过修改,如果有,则抛出ConcurrentModificationException
checkForComodification():通过判断modCount和expectedModCount值是否相等,来判断List有没有做过修改
创建迭代器的时候,会把modCount赋值给expectedModCount,调用next,remove方法时候,都会判断是否list做过修改。
如果有修改的话,抛出异常
这么做目的是啥?
ArrayList,LinkedList,HashMap都是线程不安全的,当修改ArrayList,LinkedList,HashMap时,modCount就会改变,记录修改次数,如果当前线程正在遍历ArrayList,LinkedList,HashMap时,其他线程也正在访问ArrayList,LinkedList,HashMap时,使用迭代器会抛出异常,而使用其他遍历方式,不会感知到这些,造成线程不安全
modCount 变量声明为:volatile,保证线程之间修改的可见性。
所以,这就是为什么在使用迭代器遍历,或者使用迭代器取某一个值的时候,不允许修改list自身做修改,但是迭代器自身可以remove元素。
即就是:
这样可以:
it.next();
it.remove();
这样不行:
list.remove(it.next());
推荐使用迭代器遍历非线程安全的数据结构。
总结:
非线程安全的集合类在使用迭代器遍历的时候,不能使用集合对象去修改集合,只能使用迭代器的方法去修改
迭代器只提供了移除元素的接口。