java集合
对于使用:
-
如果是集合类型,有List和Set供我们选择
-
List 插入有序,可重复
-
ArrayList 底层数据结构是数组 线程不安全
添加元素如何实现? 先去检查数组的容量是否够,够了就直接添加,不够了先扩容为当前容量的1.5倍,第一次扩容后还不够的话就直接将容量扩充为一个minCapacity(就是size+1)
增删的时候底层实现是依靠数组的复制,这个数组复制的方法由c/c++实现
-
LinkedList 底层数据结构是链表 线程不安全 还实现了Deque接口 操作他可以像操作队列和栈一样
他这个数据结构是双向链表(方便往前遍历),双向链表每个节点都存着pre和next,单链表只是每个节点存个next
关于查找 底层实现是先判断下标小于长度的一半就从头遍历,否则就从尾遍历
-
Vector 底层数据结构是数组 线程安全 现在已经很少用 被ArrayList替代
就是每个方法上加了synchronize同步,扩容的话是扩容增加1倍,ArrayList是增加0.5倍
被ArrayList替代的原因
- 所有方法都是同步, 有性能损失
- 扩容的话直接扩容增加一倍,比ArrayList更消耗内存
-
总的来说,查询多用ArrayList,增删多用LinkedList
对于数组来说如果往中间插入个值得话元素都得移动,是很可怕的
-
-
Set 插入无序 ,不可重复
-
HashSet 底层数据结构是哈希表,什么是哈希表呢?是一个数组,但是元素是链表
其实HashSet底层就是一个HashMap实例,HashSet实际就是对HashMap封装了一下,并且底层使用的HashMap的Value都是一个Object对象
-
TreeSet 底层数据结构是红黑树(一个自平衡的二叉树) 还可以保证元素的排序方式
实现了NavigableSet接口,可以实现排序,底层实际就是个TreeMap实例,非同步也就是线程不安全
-
LinkedHashSet 底层数据结构由哈希表和链表组成
迭代有序,允许为空,非同步,底层HashMap加一个双向链表(其实就是LinkedHashMap)
性能比HashSet差一点,因为要维护一个双向链表,初始容量与迭代无关,因为迭代的是那个双向链表
-
根据实际场景选择
-
-
如果是key-value型(映射)
map中key是唯一的 值是可重复的
-
Map 保持插入顺序的 选择LinkedHashMap
底层是 散列表和双向链表,允许为空 不同步 插入顺序有序(因为单链表所以致使有序)
装载因子和初始容量对LinkedHashMap影响挺大的
初始容量对遍历没有影响,因为它遍历的是LinkedHashMap内部维护着的一个双向链表,而不是一个散列表
还可以设置两种遍历顺序,访问顺序和插入顺序,访问顺序,就是如果get一个key之后,那个key就会放到map的最后面了
默认创建的map都是插入顺序,除非创建的时候加个true,就是访问顺序了。
-
不需要保持顺序就HashMap
关于HashMap:无序,允许为空,非同步,底层散列表(哈希表)实现
他还有一个装载因子这个东西,默认是0.75,有什么用呢,就是当装载因子*初始容量小于散列表元素时,该散列表会再散列,扩容2倍
初始容量默认16
HashTable有点过时了,我们需要到线程安全的地方可以使用ConCurrentHashMap
-
对排序有要求 TreeMap
为什么有序的?
因为TreeMap实现了NavigableMap接口,而这个接口继承了SortedMap接口,所以TreeMap就是有序的了
TreeMap底层是红黑树 方法的时间复杂度都不会太高:log(n)
非同步的
使用Comparator或者Comparable来比较key是否相等以及排序相关问题,只要这两个方法认为相等或者谁大谁小,然后TreeMap会听这两个方法的结果来进行排序的
如果构造方法传递了Comparator对象,就会以Comparator对象的方法进行分比较,否则就用Comparable的compareTo来进行比较
几个要点:
1. 底层红黑树,时间复杂度log(n) 2. key不能为null,否则会空指针异常 3. 想要自定义比较,在构造方法的时候传入Comparator对象即可,否则会按照自然顺序来比较(1,2,3,4,5...) 4. TreeMap非同步 想要同步可以使用Collections来封装
-
ConCurrentHashMap
JDK1.8底层是散列表+红黑树 JDK1.7是segments+HashEntry数组
支持高并发的访问和更新,线程安全
检索操作不用加锁,get方法是非阻塞的
key和value都不能为空
有了HashTable为什么还需要这个?
因为HashTable是在每个方法上都加了Synchronize完成同步,效率低,这个是通过部分加锁和利用CAS算法来实现同步
Volatile关键字,能保证变量对所有线程可见性(能让所有线程都知道此变量被修改了),但不能保证原子性(修改的过程中在jvm中分好几步,是不安全的)
-