List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。
本篇博客介绍常见的关于Java中Set集合的面试问题,结合源码分析题目背后的知识点。
关于List的博客文章如下:
关于的Set的博客文章如下:
关于HaseMap的博客文章如下:
其他相关的Set的文章如下:
1.特点:无序,去重,非线程安全;
2.底层:HashMap的Key值实现的;
3.map.put方法,静态常量PRESENT,新值替换旧值;
4.map.remove key方法,如果KEY不存在时,则返回的是null,如果KEY存在时,返回的就是e.value,即PRESENT,返回true成功,返回false不成功;
5.去重原理:先判断hash值,再通过==或者equals判断,整体如果返回true,则为重复元素;
6.无序的则采用HashSet ,有序的则采用TreeSet;
7.线程安全的set:Collections.synchronizedSet(new HashSet<>());
无参和代参构造方法都会初始化这个HashMap
无参的构造方法,调用了HashMap方法
有参的构造方法也是,调用了HashMap方法
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上
add方法中可以看出调用HashMap的put方法,key为放入元素,值为常量PRESENT
既然hashset基于hashmap实现,你说一下 hashset的add方法中,为什么要在map.put的val上放上一个Object类型的静态常量PRESENT?
HashSet底层调用了map的put方法,传入了存储的对象和PRESENT常量,那我们进入put方法继续查看
put方法内调用了putVal方法,PRESENT常量为形参value,继续进入查看
if (e != null) { // existing mapping for key
//把旧数据存储到oldValue
V oldValue = e.value;
//如果说存储的位置上已经有元素了
if (!onlyIfAbsent || oldValue == null)
//新元素会替代旧元素 新KEY替代KEY
e.value = value;
afterNodeAccess(e);
//返回旧元素数据
return oldValue;
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
//如果说上面的if结构没有执行,那么就说明这个位置上没有元素,则新增成功,返回null
return null;
public boolean add(E e) {
//上面的方法返回值决定了HashSet的add方法到底返回true还是false
return map.put(e, PRESENT)==null;
}
既然hashset基于hashmap实现,你说一下 hashset的remove方法中,为什么要在map.remove key 完了之后要和PRESENT进行一个等值比较呢?
public V remove(Object key) {
Node<K,V> e;
//判断了一下,如果removeNode删除得到的是null,说明此KEY不存在,方法返回null
return (e = removeNode(hash(key), key, null, false, true)) == null ?
//否则返回e.value 就是 PRESENT
null : e.value;
}
public boolean remove(Object o) {
//因为HashMap删除成功返回的是PRESENT , ==PRESENT 则结果为true 代表删除成功
//否则返回的是null , 返回false 删除失败
return map.remove(o)==PRESENT;
}
无序的则采用HashSet ,有序的则采用TreeSet
Set datas = Collections.synchronizedSet(new HashSet<>());
1.特点:无序,去重,非线程安全;
2.底层:HashMap的Key值实现的;
3.map.put方法,静态常量PRESENT,新值替换旧值;
4.map.remove key方法,如果KEY不存在时,则返回的是null,如果KEY存在时,返回的就是e.value,即PRESENT,返回true成功,返回false不成功;
5.去重原理:先判断hash值,再通过==或者equals判断,整体如果返回true,则为重复元素;
6.无序的则采用HashSet ,有序的则采用TreeSet;
7.线程安全的set:Collections.synchronizedSet(new HashSet<>());