目录
10. ArrayList和LinkedList的区别是什么
14. 在Queue中poll()和remove()有什么区别?
17. ConcurrentHashMap和HashTable的区别
1. 什么是集合
- 集合就是一个存放数据的容器,准确来说是放数据对象应用的容器
- 集合类存放的是对象的引用,而不是对象的本身
- 集合类型主要有三种: set(集),list(列表),map(映射)
2. 集合和数组的区别
- 数组是固定长度,集合是可变长度的
- 数组可以存放基本数据类型,也可以存放引用数据类型,集合只能存放引用数据类型
- 数组存储的元素必须是同一个数据类型,集合存储的对象可以是不同的数据类型
3. 集合框架的好处
- 容量自增长
- 提供了高性能的数据结构和算法,使编码更轻松,提高了程序的速度和质量
- 可以方便的扩展和改写集合,提高代码复用性,可操作性
- 通过使用JDK自带的集合类,可以降低代码的维护和学习性API的成本
4. 常用的集合类有哪些?
- map接口和controller接口是所有集合框架的父接口
- controller接口的子接口包括: set接口和list接口
- map接口的实现类主要有: HashMap, TreeMap, HashTable, ConcurrentHashMap以及Properties等
- Set接口的实现类主要有: HashSet, TreeSet, LinkedHashSet等
- List接口的实现类主要有: ArrayList, LinkedLisk, Stack , Vector等
5. List, Set, Map三者区别
- Java容器分为Controller和Map两大类,Controller集合的子接口有Set, List, Queue三种子接口.我们比较常用的是Set, List, Map接口不是Controller的子接口
- Controller集合主要有List和Set两大接口
- List: 一个有序容器(元素存入集合的顺序和取出的顺序一致), 元素可以重复,可以插入多个null元素,元素都有索引. 常用的实现类有ArrayList, LinkedList, Vector
- Set: 一个无序容器(存入和取出顺序可能不一致), 不可以存储重复元素, 只允许存放一个null元素,必须保证元素唯一性.set接口常用实现类是: HashSet, LinkedHashSet以及TreeSet
- Map是一个键值对,存储键,值之间的映射.key无序,唯一;value不要求有序,允许重复.map没有继承于Controller接口,从Map集合中检索元素时,只要给出键对象,就会返回对应值对象;常用实现类:HashMap, TreeMap, HashTable, LinkedHashMap, ConcurrentHashMap
6. HashMap和Hashtable有什么区别?
- 存储: HashMap运行key和value可以为null , HashTable不允许
- 线程安全: HashTable是线程安全的, HashMap非线程安全
- 推荐使用: 在Hashtable的类注释可以看到, Hashtable是保留类不建议使用,推荐单线程的环境使用HashMap替代,如果需要多线程使用则用ConcurrentHashMap替代
7. 如何决定使用HashMap还是TreeMap?
- 对于Map中插入,删除,定位一个元素这类操作, HashMap是最好的选择,因为相对而言HashMap的插入更快,但是你要对key集合进行有序的遍历,那么TreeMap是更好的选择
8. 说一下HashMap实现原理
- HashMap基于Hash算法实现, 我们通过put(key,value)存储,通过get(key)获取.当传入key时,HashMap会根据key,hashCode()计算出hash值,根据hash值将value保存在bucket中,当计算出hash值相同时,我们称之为hash冲突,HashMap的做法是用链表+红黑树存储相同hash值的value.当hash冲突的个数比较少时,使用链表,比较多时 使用红黑树.
9. 说一下HashSet的实现原理
- HashSet是基于HashMap实现的, HashSet底层使用HashMap保存所有元素,因此HashSet的实现比较简单,相关HashSet操作,基本上都是直接调用底层Hash Map的相关方法完成,但是HashSet不允许重复值.
10. ArrayList和LinkedList的区别是什么
- 数据结构实现: ArrayList是动态数组的数据结构实现,而LinkedList是双向链表的数据结构实现
- 随机访问效率: ArrayList比LinkedList在随机访问的时候效率要高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后的依次查找.
- 增删效率: 在非首尾增删操作时,LinkedList比ArrayList效率高,因为ArrayList增删操作影响数组内其他数据下标.
- 总结: 需要在频繁二点读取集合的元素时, 推荐ArrayList,而插入和删除操作较多,推荐LinkedList
11. 如何实现数组和List之间转换?
数组转List: 使用Array.asList(array)进行转换
List转数组: 使用List自带的toArray()方法
12. ArrayList和Vector的区别是什么?
- 线程安全: Vector使用了Synchronized实现线程同步,是线程安全的, 而ArrayList是非线程安全的
- 性能: ArrayList性能上优于Vector
- 扩容: ArrayList和Vctor都会根据实际的需要动态调整容量, 只不过在Vector扩容每次增加一倍,而ArrayList只会增加50%
13. Array和ArrayList有何区别?
- Array可以存储基本数据类型,ArrayList只能存储对象
- Array固定大小,ArrayList大小是自动扩展
- Array内置方法没有ArrayList多
14. 在Queue中poll()和remove()有什么区别?
- 相同点:都是返回第一个元素,并在队列中删除返回的对象
- 不同点:如果没有元素poll()会返回null,而remove()会直接抛出异常
15. 哪些集合类是线程安全的?
- 线程安全:Vector,Hashtable,Stack
- 线程不安全:HashMap
- 注意:JDK1.5以后随着Java.util.concurrent并发包出现,他们也有自己对应的线程安全类,比如HashMap对应线程安全类是ConcurrentHashMap
16. 集合底层的数据结构总结
- List
- ArrayList : Object[] 数组
- Vector:Object[] 数组
- LinkedList:双向链表(jdk1.6之前是循环链表,jdk1.7取消了循环链表)
- Set
- HashSet(无序,唯一):基于HashMap实现,底层采用HashMap保存元素
- LinkedHashSet:LinkedHashSet是HashSet子类,内部通过LinkedHashMap实现,类似LinkedHashMap内部是基于HashMap实现一样。
- TreeSet(有序,唯一):红黑树(自平衡的排序二叉树)
- Queue
- ArrayQueue:Object[] 数组+双指针
- PriorityQueue:数组实现二叉堆
- Map
- HashMap:JDK1.8之前HashMap由数组+链表组成,数组是HashMap的主体,链表则是为了解决Hash冲突的问题,Jdk8以后解决hash冲突有了较大变化,当链表长度大于阈值(默认为8)(将链表转换成红黑树前会判断,如果当前数组长度小于64,那么选择数组扩容,而不是转换成红黑树)时,将链表转换为红黑树,减少搜索时间
- LinkedHashMap:LinkedHashMap继承HashMap,底层仍然是基于拉链式散列结构,即数组和链表或红黑树组成。另外LinkedHashMap在上面结构的基础上,增加了双向链表,使上面的结构可以保持键值对的插入顺序。同时通过对链表进行相关操作,实现了访问顺序相关逻辑。
- Hashtable:数组+链表组成,数组是Hashtable的主体,链表则是主要解决hash冲突问题
- TreeMap:红黑树
17. ConcurrentHashMap和HashTable的区别
- 底层数据结构:
- ConcurrentHashMap:JDK1.7采用分段数组+链表,JDK1.8数组+链表/红黑二叉树
- HashTable:和JDK1.8以前的HashMap底层类似,都采用数组+链表,数组是HashMap主体,链表为了解决hash冲突
- 线程安全
- ConcurrentHashMap:
- JDK1.7,ConcurrentHashMap对整个桶数组进行分割分段(分段锁),每把锁只锁容器中的部分数据,多线程访问容器不同数据段数据,不会出现锁竞争,提高了并发访问效率
- JDK1.8,ConcurrentHashMap摒弃JDK1.7的概念,而是直接Node数组+链表+红黑树的数据结构实现,并发控制使用synchronized和CAS操作。整体看起来就是优化过且线程安全的HashMap
- Hashtable(同一把锁):使用synchronized保证线程安全,效率非常低。一个线程访问同步方法,其他线程也访问同步方法,可能会进入阻塞或轮询的状态,例如使用put添加元素,另一个线程不能使用put,也不能使用get
- ConcurrentHashMap: