目录
- 常见的集合有哪些?
- Collection和Collections有什么区别?
- ArrayList 和 Array(数组)的区别?
- ArrayList 和 LinkedList 的区别是什么?
- Arraylist 和 Vector 的区别
- HashMap和Hashtable的区别
- 哪些集合类是线程安全的?哪些不安全?
- HashMap原理
- 解决hash冲突有哪些方法?
- Set是怎么去重的?为什么要重写equals?
- HashSet、LinkedHashSet 和 TreeSet 的区别?
- ConcurrentHashMap新特点?
常见的集合有哪些?
Java集合类主要由两个接口Collection
和Map
派生出来的,Collection
有三个子接口:List
、Set
、Queue
。
Java集合框架图如下:
Collection和Collections有什么区别?
Collection
是一个 集合接口:它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。是list,set等的父接口。Collections
是一个 包装类:它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
ArrayList 和 Array(数组)的区别?
ArrayList 内部基于动态数组实现,比 Array(静态数组) 使用起来更加灵活:
Array
数组长度固定,ArrayList
可动态扩容。Array
可以直接存储基本类型数据,也可以存储对象。ArrayList
中只能存储对象。ArrayList
允许你使用泛型来确保类型安全,Array 则不可以。ArrayList
支持插入、删除、遍历等常见操作,并且提供了丰富的 API 操作方法,比如 add()、remove()等。Array
创建时必须指定大小,ArrayList
创建时不需要指定大小
ArrayList 和 LinkedList 的区别是什么?
- 数据结构:
ArrayList
是 动态数组 的数据结构实现,而LinkedList
是 双向链表的数据结构实现。 - 随机访问:
ArrayList
比LinkedList
随机访问效率高,因为LinkedList
是线性的数据存储方式,所以需要移动指针从前往后依次查找。 - 增删效率:在非首尾的增加和删除操作,
LinkedList
要比ArrayList
效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。
综合来说,在需要 频繁读取 集合中的元素时,更推荐使用 ArrayList
,而在 插入和删除操作较多时,更推荐使用 LinkedList
。
Arraylist 和 Vector 的区别
ArrayList
在内存不够时扩容为原来的1.5倍,Vector
是扩容为原来的2倍。- Vector属于线程安全级别的,但是大多数情况下不使用Vector,因为操作Vector效率比较低
HashMap和Hashtable的区别
- 存储:
HashMap
允许 key和 value 为null
,而Hashtable
不允许。 - 线程安全:
Hashtable
是线程安全的,而HashMap
是非线程安全的。 - 推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下使用
HashMap
替代,如果需要多线程使用则用ConcurrentHashMap
替代。
哪些集合类是线程安全的?哪些不安全?
线性安全的集合类:
Vector
:比ArrayList多了同步机制。Hashtable
。ConcurrentHashMap
:是一种高效并且线程安全的集合。Stack
:栈,也是线程安全的,继承于Vector。
线性不安全的集合类:
- Hashmap
- Arraylist
- LinkedList
- HashSet
- TreeSet
- TreeMap
HashMap原理
HashMap 使用动态数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的
链表长度大于8(TREEIFY_THRESHOLD)时,会把链表转换为红黑树
红黑树节点个数小于6(UNTREEIFY_THRESHOLD)时才转化为链表,防止频繁的转化
解决hash冲突有哪些方法?
- 链表法
- 开放地址法
- 再hash法
- 公共溢出区
Set是怎么去重的?为什么要重写equals?
HashSet底层使用的是HashMap,HashSet中的元素实际上由HashMap的key
来保存,而HashMap的value则存储了一个静态的Object对象
当判断两个对象是否相等时:
1:获取对象的hashcode,找到对应的桶位,如果没有数据,直接存,如果有数据
2:需要调用equals方法,判断是否是同一个对象,是:丢弃 不是:链表
HashSet、LinkedHashSet 和 TreeSet 的区别?
HashSet
是 Set 接口的主要实现类 ,HashSet 的底层是 HashMap,线程不安全的,可以存储 null 值;
LinkedHashSet
是 HashSet 的子类,能够按照添加的顺序遍历;
TreeSet
底层使用红黑树,能够按照添加的顺序遍历,排序的方式可以自定义
ConcurrentHashMap新特点?
Java8 中的 ConcurrentHashMap
新增了一些特点:
-
分段锁机制:
将数据分成多个 segment 来实现锁的粒度更细,从而减小锁的竞争范围,提高并发性能
-
CAS 算法:
对数据进行更新时,采用
CAS
(Compare And swap)算法来保证更新的原子性,避免了锁的颗粒度过大而带来的性能问题。 -
扩容机制:
扩容时,只需要对需要扩容的 Segment 进行扩容,而不是对整个 Map 进行扩容,这样可以减少扩容对并发性能的影响。
总之,ConcurrentHashMap 在 JDK8 中有了很大的优化和改进,减小了锁的粒度,提高了并发性能和可伸缩性,并且也是线程安全的,是AGSHI高并发环境下的一个非常优秀的容器。