面试题总结
· 57 min read
java 集合
Collection
存放单一元素
List- 有序可重复
ArrayList:Object数组,不同步,线程不安全- 内部基于动态数组实现,比
Array使用起来更灵活 - 可以添加
null值,但是不建议,会难以维护判空异常
- 内部基于动态数组实现,比
Vector:古早的以Object数组为基础的LinkedList:双向链表(1.6 之前是循环链表,1.7 取消了循环),不同步,线程不安全- 因为是由链表构成的,所以不支持随机访问,不能实现
RandomAccess接口
- 因为是由链表构成的,所以不支持随机访问,不能实现
Set- 无序不可重复
HashSet:基于HashMap实现- 检查重复:对象加入
HashSet时,会计算hashCode值来判断对象的加入位置,同时也会与其他加入的对象的hashCode的值比较,如果没有相符的,则会认为没有重复;否则,会调用equals()方法来检查hashCode相等的对象是否真的相同
- 检查重复:对象加入
LinkedHashSet:HashSet的子类,通过LinkedHashLMap实现TreeMap:红黑树实现
Queue- 按照特定顺序排序,有序可重复
Comparable:出自java.lang包,有一个compareTo(Object obj)方法Comparator:出自java.util包,有一个compare(Object obj1, Object obj2)方法
Map
以键值对形式存储
-
HashMap:1.8 之前以数组和链表组成,链表是为了解决哈希冲突存在;之后改成了数组/链表+红黑树(当链表长度超过阈值 8 时,先判断数组是否超过 64,超过,将链表转换为红黑树,没超过,先把数组扩容),线程不安全-
因为线程安全问题,效率高于
HashTable -
可以存储
Null key和Null value,但是null键只有一个,null值可以有多个 -
默认初始化大小为 16,每次扩容容量变为原来 2 倍,如果给了初始值,则每次扩容容量为 2 的幂次方大小
-
- 第一个线程:在头节点插入前被调度挂起
- 第二个线程:因为使用的是头插法,原来的头节点插入新链表后,第二个节点头插法插入同一个数组下标下的链表,线程结束
- 第一个线程:把新数组下标中存储第二个线程的更新后的那个头节点,此时尾节点的后继指向了头节点
-
1.8 后,多个线程更新同一个桶的数据会产生数据覆盖的风险
-
-
LinkedHashMap:继承自HashMap,底层是基于拉链式散列结构即数组和链表或红黑树组成,另外多加了双向链表,可以头插和尾插数据,线程不安全 -
HashTable:数组+链表,链表主要为了解决哈希冲突,线程安全(因为内部方法都是用synchronized修饰的)- 不允许存储
Null key和Null value
- 不允许存储
-
TreeMap:红黑树,线程不安全- 实现了
NavigableMap接口:有了对集合内元素搜索的能力 - 实现了
SortedMap接口:有了对集合中元素根据键排序的能力,默认是按Key的升序排序
- 实现了
