Set的非重复判断是根据什么判断的
HashSet
首先来看下HashSet的add()这个方法的源代码:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
由此可知HashSet的值是存储在一个Map的key里面的,而正好Map的key是不能重复的,以下是HashSet的部分源码:
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<E,Object>();
}
public Iterator<E> iterator() {
return map.keySet().iterator();
}
public int size() {
return map.size();
}
接着再看看HashMap里的put()方法是如何判断值是否重复的,以下是HashMap的put()源码:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
关键这句:if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
它先进行了hashCode的判断,如果hashCode相等再接着使用==来判断传入的对象的引用地址是否相等及使用传入对象的equals()方法来进行判断。
接着再看看HashSet的contains()方法的源码:
public boolean contains(Object o) {
return map.containsKey(o);
}
调用的是Map的containsKey()方法,以下是HashMap的containsKey()源码:
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k)))) 和put()方法的判断是一样的。 TreeSet
看看TreeSet的add()方法的源码:
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
它也同样是由一个Map的key来进行存储,看看这个Map:
/**
* The backing map.
*/
private transient NavigableMap<E,Object> m;
接着看看TreeSet的构造函数:
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
public TreeSet() {
this(new TreeMap<E,Object>());
}
TreeSet的无參构造函数里实例化了一个TreeMap对象,下面看看这个TreeMap对象:
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{ private final Comparator<? super K> comparator; public TreeMap() {
comparator = null;
} public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
//其他略...
}
public interface NavigableMap<K,V> extends SortedMap<K,V>
接着看这个TreeMap的put()方法:
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
// TBD:
// 5045147: (coll) Adding null to an empty TreeSet should
// throw NullPointerException
//
// compare(key, key); // type check
root = new Entry<K,V>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<K,V>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
TreeMap存储的对象是会进行排序的,所以存储的对象都必须实现Comparable接口。
TreeMap先判断Comparator对象是否为空,不为空则使用当前的Comparator对象的compare方法来进行比较排序,若发现compareTo返回的值为0,则认为这两个对象是重复的了,然后覆盖原来的value;如果Comparator对象为空,则使用集合对象实现的Comparable接口的compareTo方法来进行比较排序,同样地当返回值是0时就认为对象重复,然后覆盖原来的value。
Set的非重复判断是根据什么判断的的更多相关文章
- linux shell脚本查找重复行/查找非重复行/去除重复行/重复行统计
转自:http://blog.sina.com.cn/s/blog_6797a6700101pdm7.html 去除重复行 sort file |uniq 查找非重复行 sort file |uniq ...
- sort关于去除重复/查找非重复/查找重复/统计
去除重复sort file |uniq 查找非重复 sort file | uniq -u 查找重复 sort file | uniq -d 统计 sort file | uniq -c
- MySQL(15):Select-distinct(返回非重复的记录)
1. 查询所有记录 和 查询 非重复记录 语法: SELECT [ALL | DISTINCT ] All:返回所有记录 Distinct:返回非重复记录 针对获得的记录内的字段生效. 2. ...
- leecode第二天-使用异或找出数组中的非重复元素
leecode题目描述如下: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 思路: 最开始想到的是使用排序,排序之后就很容易找到非重复元素了. ...
- [讲解]sql except和intersect运算符(比拟两个或多个select语句的结果并前去非重复值)
图 1 UNION 中若有重复的行,会被移除,只留下一个 1.简介 EXCEPT和INTERSECT运算符使您可以比较两个或多个SELECT语句的结果并返回非重复值. 2.区别 EXCEPT运算符返回 ...
- SSAS 非重复计数
在SSAS设计时,对商品编号列非重复计数:
- 判断密码是否可见/判断登录的状态/判断在form表单中 定义rules规则验证(iview)
一: 判断密码是否可见判断:type="visiblePassword ? 'text' : 'password'" 是否为false 或者 true 密码为输入框或者文本框点击眼 ...
- dfs 全排列 使用交换——含重复元素和非重复元素
15. 全排列 中文 English 给定一个数字列表,返回其所有可能的排列. 样例 样例 1: 输入:[1] 输出: [ [1] ] 样例 2: 输入:[1,2,3] 输出: [ [1,2,3], ...
- mysql删除重复记录,只保留最大ID的记录(非重复也保留)
目前网上搜索的删除重复记录,大部分都是where子查询,本人感觉看上去不美观,故亲自手写了一个,如下: delete from mst_sku using mst_sku,( select dist ...
随机推荐
- 网站卡测试用 PageSpeed Insights
这个是google测试网页的;https://developers.google.com/speed/pagespeed/insights/ PageSpeed Insights 简介 PageSpe ...
- 梦想CAD控件 2018.10.15更新
下载地址: http://www.mxdraw.com/ndetail_10105.html 1. 完善com接口的ToCurves函数,转换CAD文字,多行文字到曲线 2. 修改DrawImage接 ...
- ES6字符串模板
这里做个简单的拓展,之前做vue组件时,经常用到拼接字符串,换行时用到\,既费时又麻烦.这里介绍个ES6字符串模板方法 旧版拼接(各种换行拼接) Vue.component('obj-prop',{ ...
- 校内测之zay与银临 (day2)(只有T1)
一些与题目无关的碎碎念 推出式子来一定要化简!!!freopen不要写错!!!特判不要瞎搞!!!! 做到以上三点能高35分qwq T1 江城唱晚 你看数据那么大,显然又是一道数学题. 这里有n个种海棠 ...
- c++行事准则
1.c++包含多种编程范式,每种范式遵循不同的准则: 2.除了#include和#ifdef之流,其他预处理器别用,多用enum和const: 3.函数声明定义多用const:
- atCoder Ants on a Circle(又是蚂蚁问题。。。)
atCoder Ants on a Circle(又是蚂蚁问题...) 传送门 题意:一个圈,蚂蚁在上面以相同的速度和不同的方向走,问t秒后它们各自的位置. 解法:和经典的蚂蚁问题一致,把相撞的情况看 ...
- 数据库——mysql如何获取当前时间---https://www.cnblogs.com/Chenshuai7/p/5136469.html
数据库——mysql如何获取当前时间 1.1 获得当前日期+时间(date + time)函数:now() -------https://www.cnblogs.com/Chenshuai7/p/51 ...
- poj 1364 查分约束
#include<stdio.h> #include<iostream> #include<stack> #include<string.h> usin ...
- [K/3Cloud]ksql翻译札记
2011-11-16 又学一招,集合转化临时表的方法: var sql = string.Format(@"select b.FENTRYID,a.{2} from {0} a inner ...
- HDU——1215 七夕节
暴力枚举....(正解好像不是这样...) 代码: #include<cstdio> #include<cstdlib> #include<cstring> #in ...