您的位置:首页 > 编程语言 > Java开发

Java集合学习笔记

2010-08-04 23:05 239 查看
集合分析:

1。 ArrayList

基于数组实现(Object[] elementData)、实现随机操作(RandomAccess接口)非线程安全。

ensureCapacity(add方法可能要进行数组扩容,计算公式为(oldCapacity * 3)/2 + 1)、trimToSize等使用Arrays.copyOf。

Arrays.copyOf方法实现(参见源码), 如果是Object类型,则直接通过new Object[newLength]创建;否则通过Array.newInstance创建; 然后调用System.arraycopy将之前数组中的对象复制到新的数组中(native方法)。

add(int, E)的实现,要将当前数组对象进行一次复制(index后数组后移一位)。

remove操作调用的是fastRemove, 要将当前数组对象进行一次复制(index后的数组前移一位); remove(int)的实现比remove(E)多了一个数组范围检测, 但少了对象查找, 因为性能更好。

2。LinkedList

基于双向链表机制(采用E和next、previous的Entry<E> 对象)、实现双向队列操作(Deque接口--对向队列、队列、堆栈)、非线程安全。

add的实现(不需要扩容与数组复制),remove(不需要数组复制),但都需要改变next、previous的指向来保持双向队列。

3。HashSet

基于HashMap实现、非线程安全。

不允许元素重复。

add(E)调用put(K, V)来完成操作, value为类的static final Object。

4。TreeSet

基于TreeMap,支持排序, 非线程安全。

add(E)调用put(K, V)来完成操作, value为类的static final Object。

5。HashMap

采用Entry对象数组(采用key、value、next、hash的Entry<K,V>对象)、非线程安全。

基于key hash寻找Entry对象存放到数组的位置,对于hash冲突采用链表方式来解决。(threshold = (int)(capacity * loadFactor))

put操作可能要对Entry对象数组进行扩容(resize方法,计算公式为2 * table.length), 需要对扩大容量后对象数组重新hash并复制对象到新的数组中(对每个key对象的hasCode进行indexFor得到bucketIndex,在放入数组位置为bucketIndex中),最后设置threshold值。

6。TreeMap

基于红黑树的实现、支持排序(可使用带Comparator参数的构造器, 或key对象实现Comparable接口), 非线程安全。

集合包测试:

单线程测试

1。从整体来看,List几个实现类, 当元素数量多时,删除、查找性能大幅度下降,增加性能稍微下降, 而Set和Map基本没什么变化。

2。从List来看,对于元素数量少时,增加、删除、查找LinkedList性能好;对于元素数量多时,增加LinkedList性能好,删除、查找ArrayList性能好。

多线程并发测试:

1。从整体来看,在多线程时各集合性能下降明显,并随着线程数量增加, 下降得就越多, 相对而言Set和Map的实现表现好一些。

2。从List来看,对于元素数量少时,增加、删除、查找LinkedList性能好;对于元素数量多时,增加、删除、查找ArrayList性能好。

集合包小结:

List适用于允许重复元素的单个对象集合场景,Set适用于不允许重复元素的单个对象集合场景,Map适用于key-value结构集合场景。

ArrayList适用于通过位置来读取元素的场景(随机读取),LinkedList适用于头尾操作及插入指定位置的场景。

(线程不安全, 调用iterator()后, 在遍历过程中如有元素的增加或删除, 则会抛出ConcurrentModificationException)

学习参考资料:

《分布式Java应用:基础与实践》、jdk7类库源码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: