1、有几种常见集合?各有什么特点?
Collection是所有集合类的根接口,Collections是提供集合操作的工具类,常用的集合有:
Set代表无序集合,无序不可重复,有HashSet,TreeSet
List代表有序集合,有序可重复,有ArrayList,LinkedList
Map集合存储键值对,常用的有HashMap,TreeMap
2、在哪些场景使用这些集合?
List里存放的对象是有序的,同时也是可以重复的,其特点是List关注的是索引,拥有一系列和索引相关的方法,查询速度快,往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。
ArrayList是基于数组的,在初始化ArrayList时,会构建空数组,当发觉同时添加一个或者是多个元素,数组长度不够时,就扩容。
LinkedList是基于链表的,它是一个双向链表,每个节点维护了一个prev和next指针。
总结:根据其特点,经常使用查询,list的实现类如ArrayList可以提供更快速的访问,如果经常添加删除元素,选择LinkedList基于链表更快的删除,如果想让容器的元素能够按照他们的插入次序进行有序存储,使用List,List是一个有序容器,他按照插入顺序进行存储。
Set不允许有重复对象,无序容器,无法保证每个元素的存储顺序,TreeSet通过Comparator维护一个排序顺序,如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个 Set 的实现类,比如 HashSet、LinkedHashSet 或者 TreeSet。
以键和值的形式进行数据存储那么 Map。
private Set<Role> roles = new HashSet<Role>();
List list = new ArrayList<User>();
//将查询条件封装到map中
Map<String,Object> map = new HashMap<String,Object>();
map.put("reportDate", reportDate);
3、HashSet是怎么保证唯一性的?
HashSet的底层存储数据结构是哈希表, 它是根据哈希值和equals方法来确保集合元素的唯一性
原理:如果一个元素要存入,首先会判断集合是否存在与该元素的HashCode相同的元素, 如果不存在,则把元素存入HashSet集合,如果存在,则继续调用equals继续比较,如果equals方法返回true,证明集合已经存在该元素,所以不添加,如果返回false,证明该元素在集合中存在一个相同哈希值,内容不同的元素,所以把该元素添加到与该元素相同哈希值的元素后面。
4、HashMap的底层结构,实现原理?
JDK1.8之前
JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n-1)&hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。
所谓扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞。
JDK 1.8 HashMap 的 hash 方法源码:
static final int hash(Object k){
int h;
// key.hashCode();返回散列值也就是hashcode
// ^ : 按位异或
// >>> : 无符号右移,忽略符号位,空位都已0补齐
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
复制代码
对比一下 JDK1.7的 HashMap 的 hash 方法源码.
static final int hash(int h){
h ^= (h >>> 20) ^ (h >>>12);
return h ^ (h >>> 7) ^ (h >>>4);
}复制代码
相比于JDK1.8 的hash 方法 ,JDK 1.7 的hash 方法的性能会稍差一点点,因为毕竟扰动了4 次。
所谓 “拉链法” 就是:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。
JDK1.8之后
相比于之前的版本,JDK1.8之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。
TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
编辑| Web小项目
作者:junxia
如果您认为阅读这篇博客让您有些收获,欢迎扫描下方二维码关注我们,与我们交流互动。
本公众号专注Java面试题目的收集和解析以及【Web项目】源码的分享。
以下为公众号截图,欢迎小伙伴们鼓励!