第一题 介绍一下java中的容器
第二题 Collection和Collections的区别
1、Collection是一个接口,提供了集合的相关规范,比如add,remove,contains等方法
2、Collections是一个工具类,提供了一系列的静态方法,比如集合的排序,搜索等
第三题 ArrayList和LinkedList的区别
1.实现原理不同:ArrayList是基于数组实现的一个动态数组,LinkedList是基于链表实现的双向循环链表。
2.各自特性:
(1)由于ArrayList是基于数组实现,而数组是申请的一块连续的内存,所以ArrayList在随机访问方面表现的比较出色。
(2)LinkedList是基于链表实现,所以在删除,插入操作表现比ArrayList好。
(3)ArrayList在不指定容量初始化时,是默认初始化一个空数组,在执行add()方法时会初始化为一个容量为10的数组,后续每次扩容都是以当前容量的1.5倍扩容,
最大容量为Integer.MAX_VALUE-8;由于ArrayL每次扩容都涉及数组的拷贝,浪费性能,所以初始化的时候尽量给一个合理容量。
(4)LinkList实现了队列接口,所以具有队列的特性。比如offer()和poll()方法。
第四题 说一下HashMap
1.结构:HashMap基于哈希表的Map接口实现,是以key-value存储形式存在。JDK1.7以前是数组+链表实现,JDK1.8以后是数据+链表+红黑树实现。
2.特性:
(1)HashMap由于是根据key的hash值来确认元素的位置,所以是不能确定插入数据的顺序性的。
(2)HashMap是线程不安全的。
(3)HashMap允许key和value都为空,但是键位置只能是一个null
3.初始化与扩容
(1)初始化
在使用无参构造器初始化时,是只会初始化一个容量为0.75的加载因子。使用指定容量的构造器初始化,则会初始化一个大于且最接近初始容量的2的n次幂大小的HashMap。
比如: Map map = new HashMap(7);//初始化后,实际数组大小为8
(2)扩容机制
当HashMap中的元素个数超过数组大小(数组长度)loadFactor(负载因子)时,就会进行数组扩容,即扩大一倍;比如:数组大小为16时,当元素个数达到12(160.75)时,数组长度就会扩容到32。
重点:当jdk1.8后,当数组上某一链表的长度大于8,且数组长度大于64时,链表则会转换为红黑树,节点类型由Node转换为TreeNode;当下次执行resize()方法时判断树的节点个数小于6时,则会把树结构转回为链表结构。
4.HashMap的put方法与Hash冲突
第五题 HashMap和HashTable的区别
1、HashMap 允许键值对都为null
2、HashTable 不允许键值对为null
3、HashMap是线程不安全的,HashTable是线程安全的,所以HashMap效率较高一点
第六题 HashTable和ConcurrentHashTable的区别
1、HashTable使用synchronized保证线程安全,效率低下,当一个线程访问同步方法时,另一个线程也访问就会陷入阻塞状态。
2、 ConcurrentHashTable在jdk1.8以后是采用 Node 数组 + 链表 / 红黑树结构,使用synchronized和cas,锁住的链表的头结点或树的第一个节点。
多线程与并发篇
第一题 说一说synchronized
1、总体:简单来说,synchronized是java基于JVM层面的一把对象锁,主要作用是保证代码执行的原子性、一致性、有序性,从而确保并发下代码的安全性。
- 原子性:synchronized 修饰的代码,同一时间只能被同一线程访问,代码块中是通过字节码层面的monitorenter 和 monitorexit 指令,方法上是通过访问ACC_SYNCHRONIZED 标志。
- 一致性:被synchronize的修饰的代码中,线程访问时都会先从主存中同步变量
- 有序性:synchronized 修饰的代码,同一时间只能被同一线程访问。(如果在本线程内观察,所有操作都是天然有序的)注意,synchronized 是无法禁止指令重排和处理器优化的,但是同一线程内的执行遵守 as-if-serial 语义。
2、用法:
(1)、synchronized作用于代码块上:相当于给此段代码加锁,锁住的是自定义的对象。在代码被编译成字节码文件后,此段代码最前面会增加一个monitorenter指令,最后面会有一个monitorexit指令。当线程执行到monitorenter 指令时,会去尝试获取monitor(监视锁),获取到monitor就相当于获取到锁了,这时monitor计数器自增变为 1,当线程执行完代码块,就会释放monitor,这时monitor计数器自减变为 0。
(2)、synchronized作用于方法上: