一、Java基础
(一)集合
-
List接口:有序可重复
-
LinkedList:基于链表实现,每个元素储存本身内存地址还储存下一个元素的地址。(增删快,查找慢)
-
ArrayList:基于数组实现,每次增删都要重新创建新的数组,但数组有索引。(增删慢,查找快)
-
Vector:基于数组,线程安全相关,效率低。
-
-
Set接口:不可重复
-
HashSet: 储存的元素无序,不可重复,底层是哈希表
-
LinkedHashSet:储存元素有序,不可重复,底层是哈希表和链表的结合
-
TreeSet:可以指定一个顺序,对象存入之后会按照指定的顺序排序。
-
-
Map接口:双列集合
-
HashMap:非线程安全,高效,支持null
-
LinkedHashMap:是HashMap的一个子类,保存了记录的插入顺序
-
HashTable:线程安全,低效,不支持null
-
TreeMap:能够把他保存的记录根据键排序,默认是键值的升序排序
-
1.HashMap和Hashtable有什么区别?
-
存储: HashMap 运行key和value可为null,而Hashtable不允许。
-
线程安全: Hashtable 是线程安全的,而HashMap是非线程安全的。
2.HashMap的实现原理
-
HashMap基于Hash算法实现的,我们通过put(key,value)存储,get(key)来获取;
-
当传入key时,HashMap 会根据key. hashCode()计算出hash值,根据hash值将value保存在bucket里;
-
当计算出的hash值相同时,我们称之为hash冲突,HashMap 的做法是用链表和红黑树存储相同hash值的value;
-
当hash冲突的个数比较少时,使用链表否则使用红黑树。
3.ArrayList和LinkedList的区别是什么?
-
数据结构实现: ArrayList是动态数组的数据结构实现,LinkedList是双向链表的数据结构实现。
-
随机访问效率: ArrayList 比LinkedList 在随机访问的时候效率要高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
-
增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比ArrayList效率要高,因为ArrayList增删操作要影响数组内的其他数据的下标。
-
综合来说,在需要频繁读取集合中的元素时,更推荐使ArrayList,而在插入和删除操作较多时,更推荐使用LinkedList。
4.ArrayList和Vector的区别是什么?
-
线程安全: Vector使用了Synchronized 来实现线程同步,是线程安全的,而ArrayList是非线程安全的。
-
性能: ArrayList在性能方面要优于Vector。
-
扩容: ArrayList和Vector都会根据实际的需要动态的调整容量,只不过在Vector扩容每次会增加1倍,而ArrayList只会增加50%。
5.Array和ArrayList有何区别?
-
Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。
-
Array 是指定固定大小的,而ArrayList大小是自动扩展的。
-
Array内置方法没有ArrayList多,比如addAll、 removeAll、 iteration等方法只有ArrayList有。
6.哪些集合类是线程安全的?
-
Vector、Hashtable、 Stack 都是线程安全的,而像HashMap则是非线程安全的;
-
不过在JDK 1.5之后随着Java. util. concurrent并发包的出现,它们也有了自己对应的线程安全类,比如HashMap对应的线程安全类就是ConcurrentHashMap。
(二)线程
线程三种队列:
LinkedBlockingDeque(链表同步阻塞队列)、ArrayBlockingQueue(数组同步阻塞队列)、SynchronousQueue(同步阻塞队列)
1.创建线程有三种方式
-
继承Thread重写run方法;
-
实现Runnable接口;
-
实现Callable 接口。
-
runnable没有返回值,callable 可以拿到有返回值,callable 可以看作是runnable的补充。
2.线程的状态:
-
NEW尚未启动
-
RUNNABLE正在执行中
-
BLOCKED阻塞的(被同步锁或者I0锁阻塞)
-
WAITING 永久等待状态
-
TIMED_ WAITING 等待指定的时间重新被唤醒的状态
-
TERMINATED执行完成
3.线程池创建有七种方式,最核心的是最后一种:
-
newSingleThreadExecutor(): 它的特点在于工作线程数目被限制为1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一一个任务处于活动状态,并且不允许使用者改动线程池实例,因此可以避免其改变线程数目;
-
newCachedThreadPool(): 它是一种用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程;如果线程闲置的时间超过60秒,则被终止并移出缓存;长时间闲置时,这种线程池,不会消耗什么资源。其内部使用SynchronousQueue作为工作队列;
-
newFixedThreadPol(int nThreads):重用指定数目(nThreads) 的线程,其背后使用的是无界的工作队列,任何时候最多有nThreads个工作线程是活动的。这意味着,如果任务数量超过了活动队列数目,将在工作队列中等待空闲线程出现;如果有工作线程退出,将会有新的工作线程被创建,以补足指定的数目nThreads;
-
newSingleThreadScheduledExecutor() :创建单线程池,返 回ScheduledExecutorService,可以进行定时或周期性的工作调度;
-
newScheduledThreadPool(intcorePoolSize)和 newSingleThreadScheduledExecutor()类似创建的是个ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多