Java集合
Java中常见的数据结构有哪些?
-
数组
-
链表
-
栈
-
队列
-
图
-
树
-
哈希表
Java稽核框架指的什么
集合框架是java的一种工具类,是用来代表和操纵集合的统一架构。
其中:
- Collection接口和Map接口分别是所有集合类的父接口
- Collection接口的子接口包括Set和List
- Map接口的实现类主要有HashMap、TreeMap、HashTable和Properties等
- Set接口的实现类主要有HashSet、TreeSet和LinkedHashSet等
- List接口的实现类主要有ArrayList、LinkedList、Stack和Vector等
通过使用Java自带的集合框架,可以降低我们代码维护成本和开发成本,并且集合框架本身还有高复用性和可操作性的特点,且经过严格测试,可以提高我们的代码质量。
ArrayList和LinkedList有什么区别?
ArrayList底层结构是数组,LinkedList底层结构是链表。它们都支持位置索引来实现随机访问,只不过ArrayList的位置索引是显示索引,LinkedList的位置索引是隐式索引。
因为底层结构的差异,对于随机访问get和set,ArrayList性能是要优于LinkedList;而对于非尾部的新增和删除操作,LinkedList性能更优,因为ArrayList要移动数据。
还有在遍历它们的时候,如果不使用自带的foreach方法和foreach语法糖的话,则对于ArrayList会使用简单的for循环,对于LinkedList就使用Iterator,LinkedList返回的迭代器中实际就是通过指针节点遍历链表的方式;这也是基于它们底层结构的区别来决定的,因此,应该避免使用for循环(i=0,i<n,i++这种for循环)来遍历LinkedList。
如果使用自带的foreach方法,在ArrayList在foreach方法中使用的还是for循环的方式,在LinkedList中则使用的是默认的Iterator遍历。
对于foreach语法糖模式,在编译的时候实际上使用的是Iterator遍历的方式;LinkedList与使用foreach方法是一致的,而ArrayList在返回的迭代器对象中也还是使用的for循环的方式。
ArrayList扩容
ArrayList默认是1.5倍扩容,初始容量为10。
讲一讲快速失败(fail-fast)和安全失败(fail-safe)
快速失败(fail-fast)
在对非线程安全的集合进行遍历开始的时候,会记录当前的一个modCount,代表对集合修改的操作次数,在遍历过程中,会比对当前时刻的modCount是否和集合开始的时候的modCount一致,如果不一致,代表这个集合被其他线程修改过,就会抛出ConcurrentModificationException异常。
如果是在并发的时候出现这个异常,可以将集合换成线程安全的集合,如Concurrent开头的类,或在操作的时候进行加锁。
如果是在单个线程进行遍历集合的时候想进行修改的话,可以使用迭代器进行修改,如果是List,还可以使用ListIterator,它增加了pre系列的方法和add、set方法。
安全失败(fail-safe)
采用安全失败机制的集合容器,在遍历时不是直接在原集合内容上进行访问的,而是先复制原有集合内容,然后在这份拷贝的集合上进行遍历。由于迭代的时候是对原有集合的拷贝进行比那里,所以在遍历过程中对原有集合所做的修改并不会被迭代器检测到,所以不会触发ConcurrentModificationException异常。
JUC包下的容器都是安全失败,可以在多线程环境下并发使用,并发修改。
说说ConcurrentModificationException异常(快速失败机制“fail-fast”)
在对非线程安全的集合进行遍历开始的时候,会记录当前的一个modCount,代表对集合修改的操作次数,在遍历过程中,会比对当前时刻的modCount是否和集合开始的时候的modCount一致,如果不一致,代表这个集合被其他线程修改过,就会抛出ConcurrentModificationException异常。
如果是在并发的时候出现这个异常,可以将集合换成线程安全的集合,如Concurrent开头的类,或在操作的时候进行加锁。
如果是在单个线程进行遍历集合的时候想进行修改的话,可以使用迭代器进行修改,如果是List,还可以使用ListIterator,它增加了pre系列的方法和add、set方法。