集合中的一些面试题




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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值