集合使用List、Map、Set
List接口、Set接口继承自Collection接口,Map接口无继承父接口
- 线程安全:HashTable、ConcurrentHashMap、Vector、StringBuffer
- 非线程安全:LinkedList、ArrayList、HashSet、HashMap、TreeMap、StringBuilder
List、Set、Map初识
List
- 有序
- 可重复
- 支持下标,for循环,迭代器遍历
- 长度可动态增长
- 查找元素效率高
- 插入删除效率低(会引起其他元素位置改变)
Set
- 无序(集合中元素由HashCode决定顺序、集合中对象需重写equals())
- 不可重复(重复被覆盖)
- 仅支持迭代器遍历(无序,无法用下标获取值)
- 查找元素效率低
- 插入删除效率高(不会引起其他元素位置改变)
Map
- 存储键值对数据
List、Set、Map使用
List
ArrayList使用
-
- 基于动态数组的数据结构,因地址连续索引取值效率高,但会导致插入和删除效率低(需移动数据)
# ArrayList.kt
# 索引取值速度快
fun get(index: Int): E {
if (index >= size)
throw IndexOutOfBoundsException(outOfBoundsMsg(index))
return elementData[index] as E
}
fun set(index: Int, element: E): E {
if (index >= size)
throw IndexOutOfBoundsException(outOfBoundsMsg(index))
val oldValue = elementData[index] as E
elementData[index] = element
return oldValue
}
# 插入会先判断是否需扩容,中间插值会涉及其他元素操作,将其后元素偏移1位,效率自然降低
fun add(index: Int, element: E) {
if (index > size || index < 0)
throw IndexOutOfBoundsException(outOfBoundsMsg(index))
// Increments modCount!!
ensureCapacityInternal(size + 1)
System.arraycopy(elementData, index, elementData, index + 1, size - index)
elementData[index] = element
size++
}
# 删除元素需将其后元素向前偏移1位,效率自然降低
fun remove(index: Int): E {
if (index >= size)
throw IndexOutOfBoundsException(outOfBoundsMsg(index))
modCount++
E oldValue = (E) elementData[index]
int numMoved = size - index - 1
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved)
// clear to let GC do its work
elementData[--size] = null
return oldValue
}
-
- 支持快速随机查找
# ArrayList.kt
class ArrayList<E> : AbstractList<E>, List<E>, RandomAccess, Cloneable, java.io.Serializable {
// RandomAccess是支持快速随机访问的标记
}
# Collections.kt
# ArrayList的indexOf和lastIndexOf分别是从头和尾遍历查找,显然比Collections中二分查找效率低
fun <T> binarySearch(list: List<Comparable<T>?>, key: T): Int {
return if (list is RandomAccess || list.size < Collections.BINARYSEARCH_THRESHOLD)
Collections.indexedBinarySearch<T>(list, key)
else
Collections.iteratorBinarySearch<T>(list, key)
}
LinkedList使用
- LinkedList基于链表的数据结构,因地址任意,所以开辟内存空间无需等连续地址,相应的插入和删除效率高,但查询效率低(需移动指针)
Vector使用
- Vector基于数组的数据结构,是线程安全的,通过synchronized修饰实现,线程同步,效率比ArrayList稍差,所以很少使用;同样采用连续空间存储元素,但扩容方式与ArrayList不同(Vector可设置增长因子,ArrayList不可以)
3种List使用对比
- 需对数据进行多次增删改操作时采用LinkedList
- 对数据访问较高场景采用ArrayList
- 不考虑线程安全场景ArrayList比Vector效率高
Set
HashSet、TreeSet使用
- HashSet是基于哈希表的数据结构,数据无序,可存入null(只能放一个,不可重复),放入对象需实现hashCode()(是以hashCode作为标识),因具有相同内容的String对象hashCode一致,所以不可重复,但同一个类对象可放入不同实例
- TreeSet是基于二叉树(红黑树)的数据结构,数据自动排序,不可存入null值
- HashSet基于Hash算法实现,性能优于TreeSet,无需排序功能优先使用HashSet
Map
HashMap、TreeMap、HashTable、ConcurrentHashMap使用
- HashMap基于哈希表(散列表)的数据结构,添加的键类需重写hashCode()和equals(),允许空键值,可以使用初始容量和负载因子优化HashMap内存使用。散列表冲突处理方式:开放定址法、链表法。HashMap采用链表法
- TreeMap基于红黑树的数据结构,非线程安全,该树处于平衡状态
- HashTable线程安全,效率比HashMap低,不允许空键值
- ConcurrentHashMap作为一种线程安全且高效的哈希表解决方案(分段锁方案),相比HashTable的全表锁性能提高很多
- HashMap适用于Map中插入、删除、查找元素
- TreeMap适用于按自然顺序或自定义顺序遍历键值