java中单列的常用的集合
List的实现类(常用)
Vector
- Vector是底层是数组实现,是线程安全的,效率比较低,他的实现有 synchronized。
- Vector底层也是一个对象数组,protected Object[] elementData;
- 在开发中,需要线程同步安全时,考虑使用Vector
- 如果是无参,默认10,满后,就按2倍扩容
- 如果指定大小,则每次直接按2倍扩
Arraylist
他有三种构造器
- Arraylist是底层是数组实现,是线程不安全的,效率比较高,他的实现没有 synchronized。
- ArrayList中维护了一个Object类型的数组elementData transient Object[] elementData。
- 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
- 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容则直接扩容elementData为1.5倍。
LinkedList
- 线程不安全的,有 synchronized。
- 底层维护一个双向链表,LinkedList中维护了两个属性first和last分别指向首节点和尾节点
- LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
Set的实现类(常用)
Set的公共特性
- 无序(添加和取出的顺序不一致),但是保存后顺序不会改变(连续遍历10次输出顺序都相同)
- 没有索引,不允许重复元素,所以最多包含一个null
- 可以利用不重复的特性来对数据去重
HashSet
- HashSet实现了Set接口
-
- 可以存放null值,但是只能有一个
- HashSet不保证元素是有序的,取决于hash后,再确定索引的结果
- 不能有重复元素
- HashSet实际上是HashMap,底层代码如下,HashMap的底层是(数组+链表+红黑树)
public HashSet() {
map = new HashMap<>();
}
HashSet的扩容原理
- HashSet 底层是 HashMap
- 添加一个元素时,先得到hash值-会转成-> 索引值找到存储数据表table,看这个索引位置是否已经存放的有元素如果没有,直接加入如果有, 调用 equals 比较,如果相同,就放弃添加,如果不相同,则添加到最后
- 在Java8中,如果一条链表的元素个数超过 TREEIFY THRESHOLD(默认是 8),并且table的大小 >=MIN TREEIFY CAPACITY(默认64)就会进行树化(红黑树)
- 如果链表的元素个数达到8个但是table没有到达64,则table会翻倍(2倍扩)
LinkedHashSet
- LinkedHashSet 是 HashSet 的子类
- LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个 数组+ 双向链表
- LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
- LinkedHashSet 不允许添重复元素
TreeSet
最大的区别:TreeSet可以排序
使用无参构造TreeSet的时候,仍然是无序的集合,但是使用有参构造器,Comparable,可以自定义排序方法
底层实现是TreeMap
Map
- Map 中的 key 和 value 可以是任何引用类型的数据,会封装到HashMap$Node对象中
- Map 中的 key 不允许重复,原因和HashSet 一样,Map 中的 value 可以重复
- Map 的key 可以为 null, value 也可以为null ,注意 key 为null,只能有一个value 为null 可以多个
- 常用String类作为Map的 key
- key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
HashMap
- 线程不安全的
- HashMap底层维护了Node类型的数组table,默认为null当创建对象时,将加载因子(loadfactor)初始化为0.75
- 当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key是否和准备加入的key相等,如果相等,则直接替换val; 如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。
- 第1次添加,则需要扩容table容量为16,临界值(threshold)为12
- 以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,即24,依次类推
- 在Java8中,如果一条链表的元素个数超过 TREEIFY THRESHOLD(默认是 8),并且table的大小 >= MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树)
HashTable
- 存放的元素是键值对: 即 K-V
- hashtable的键和值都不能为null
- hashTable 使用方法基本上和HashMap一样
- hashTable 是线程安全的,hashMap 是线程不安全的
- 底层有数组 HashtablesEntry[] 初始化大小为 11
- 临界值 threshold 8 = 11 * 0.75
- 扩容: 按照自己的扩容机制来进行即可,按照 int newCapacity = (oldCapacity << 1) + 1的大小扩容,即乘2+1
TreeMap
可以按照键排序
使用无参构造TreeMap的时候,仍然是无序的集合,但是使用有参构造器,Comparable,可以自定义排序方法