关于java:集合中的一些面试题

45次阅读

共计 2855 个字符,预计需要花费 8 分钟才能阅读完成。

Array 和 ArrayList 区别

Array 存储根本数据类型和对象,ArrayList 存储对象
Array 指定固定大小,ArrayList 大小可变
Array 内置办法少,ArrayList 内置办法多

ArrayList 和 LinkedList 的区别是什么?

数据结构实现: ArrayList 是动静数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。
随机拜访效率: ArrayList 比 LinkedList 在随机拜访的时候效率要高,因为 LinkedList 是线性的数据存储形式,所以须要挪动指针从前往后顺次查找。
减少和删除效率: 在非首尾的减少和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其余数据的下标。

ArrayList 和 Vector 异同

同:
实现 List 接口;底层采纳可变数组
异:
性能: ArrayList 在性能方面要优于 Vector。
线程平安:
ArrayList 非线程平安,线程不同步,单线程拜访汇合
Vector 应用了 Synchronized 来实现线程同步,是线程平安的,多线程拜访汇合
扩容:
有初始容量大小,ArrayList 扩容增长原来的 0.5 倍
有初始容量大小,Vector 扩容增长原来的 1 倍

ArrayList 为什么取代 Vector

Vector 类所有的办法都是同步的。能够由两个线程平安地拜访一个 vector 对象,然而一个线程拜访 vector 的话要在同步操作上消耗大量工夫。

ArrayList 不是同步的。所以在不须要保障线程平安时倡议应用 ArrayList。

ArrayList 与 LinkedList 区别

同:
都是 List 接口的实现类
都是非线程平安的
都允许值为空
异:
底层实现:数组 —- 双向链表
更适宜:查问 / 遍历 —- 增删
扩容:有 —- 无
继承自:AbstractList—-AbstractSquentialList

如何实现数组和 list 之间的转换

· 数组转 List:应用 Arrays. asList(array) 进行转换。
· List 转数组:应用 List 自带的 toArray() 办法。
代码示例:

**// list to array**
List<String> list = new ArrayList<String>();
list. add("previous");
list. add("的博客");
list. toArray();// array to list
String[] array = new String[]{"previous","的博客"};
Arrays. asList(array);
HashMap 和 HashTable 区别

存储: HashMap 容许 key 和 value 为 null,而 Hashtable 不容许。
线程平安: Hashtable 是线程平安的,而 HashMap 是非线程平安的。
举荐应用: 在 Hashtable 的类正文能够看到,Hashtable 是保留类不倡议应用,举荐在单线程环境下应用 HashMap 代替,如果须要多线程应用则用 ConcurrentHashMap 代替。

HashMap 和 TreeMap

对于在 Map 中插入、删除、定位一个元素这类操作,HashMap 是最好的抉择,因为相对而言 HashMap 的插入会更快,但如果你要对一个 key 汇合进行有序的遍历,那 TreeMap 是更好的抉择。

HashMap 和 LinkedHashMap

都容许键值为 null

HashMap 无序 LinkedHashMap 有序

底层实现不同

HashMap 和 ConcurrentHashMap

JDK1.8 版本的 ConcurrentHashMap 的数据结构曾经靠近 HashMap,相对而言,ConcurrentHashMap 只是减少了同步的操作来管制并发,从 JDK1.7 版本的 ReentrantLock+Segment+HashEntry,到 JDK1.8 版本中 synchronized+CAS+HashEntry+ 红黑树。

HashMap 非线程平安,ConcurrentHashMap 线程平安的

HashMap 容许键值为空,ConcurrentHashMap 不容许键值为空

HashMap 和 HashSet 底层实现

HashMap 基于 Hash 算法实现的,咱们通过 put(key,value)存储,get(key)来获取。当传入 key 时,HashMap 会依据 key. hashCode() 计算出 hash 值,依据 hash 值将 value 保留在 bucket 里。当计算出的 hash 值雷同时,咱们称之为 hash 抵触,HashMap 的做法是用链表和红黑树存储雷同 hash 值的 value。当 hash 抵触的个数比拟少时,应用链表否则应用红黑树。1.8 之前数组 + 链表;1.8 之后数组 + 红黑树

HashSet 是基于 HashMap 实现的,HashSet 底层应用 HashMap 来保留所有元素,因而 HashSet 的实现比较简单,相干 HashSet 的操作,基本上都是间接调用底层 HashMap 的相干办法来实现,HashSet 不容许反复的值。

HashMap 长度为什么是 2 的幂次方

为了让 HashMap 存取高效,尽量减少碰撞,也就是尽量把数据调配平均。因为 Hash 值的取值范畴是 -2147483648 至 2147483647,加起来大略有 40 亿映射空间,只有哈希函数映射的比拟平均涣散,个别利用是很难呈现碰撞的。但问题是一个 40 亿长度的数组,内存是放不下的。所以这个散列值不能间接哪来用,用之前还要对数组的长度取模运算,失去的余数才是要寄存这个地位也就是对应的数组下标。这个数组下标的计算方法是(n-1)&hash,这就解释了 HashMap 的长度为什么是 2 的幂次方了。

HashMap 多线程导致死循环

次要起因在于并发下的 Rehash 会造成元素之间会造成一个循环链表。不过 jdk1.8 后解决了这个问题,但还是不倡议在多线程下应用 HashMap,因为多线程下应用 HashMap 还是会存在其余问题,比方数据失落。并发环境下举荐应用 ConcurrentHashMap。

ConcurrentHashMap 和 Hashtable

底层数据结构: ConcurrentHashMap jdk1.8 前底层采纳的是分段数组 + 链表,jdk1.8 底层采纳的是数组 + 链表 / 红黑树;Hashtable 在 jdk1.8 之前采纳数组 + 链表

线程平安的形式:
ConcurrentHashMap jdk1.8 前分段锁,对整个同数组进行分段(segment),每一把锁只锁容器中一部分数据,多线程拜访容器中不同数据段的数据,就不会存在锁竞争,进步并发访问率。Jdk1.8 后,摒弃分段概念,间接应用 Node 数组 + 链表 + 红黑树的数据结构来实现,并发管制应用 synchronized 和 CAS 来操作。

HashTable(同一把锁):应用 synchronized 来保障线程平安,效率非常低下。当一个线程拜访同步办法时,其余线程也拜访同步办法,可能会进入阻塞或轮询状态。

                      如果文章对你有帮忙
                    记得点赞 + 分享 + 转发
                    

正文完
 0