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的非重复判断是根据什么判断的的更多相关文章

  1. linux shell脚本查找重复行/查找非重复行/去除重复行/重复行统计

    转自:http://blog.sina.com.cn/s/blog_6797a6700101pdm7.html 去除重复行 sort file |uniq 查找非重复行 sort file |uniq ...

  2. sort关于去除重复/查找非重复/查找重复/统计

    去除重复sort file |uniq   查找非重复 sort file | uniq -u   查找重复 sort file | uniq -d   统计 sort file | uniq -c

  3. MySQL(15):Select-distinct(返回非重复的记录)

    1. 查询所有记录 和 查询 非重复记录 语法: SELECT    [ALL | DISTINCT ] All:返回所有记录 Distinct:返回非重复记录 针对获得的记录内的字段生效.   2. ...

  4. leecode第二天-使用异或找出数组中的非重复元素

    leecode题目描述如下: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 思路: 最开始想到的是使用排序,排序之后就很容易找到非重复元素了. ...

  5. [讲解]sql except和intersect运算符(比拟两个或多个select语句的结果并前去非重复值)

    图 1 UNION 中若有重复的行,会被移除,只留下一个 1.简介 EXCEPT和INTERSECT运算符使您可以比较两个或多个SELECT语句的结果并返回非重复值. 2.区别 EXCEPT运算符返回 ...

  6. SSAS 非重复计数

    在SSAS设计时,对商品编号列非重复计数:

  7. 判断密码是否可见/判断登录的状态/判断在form表单中 定义rules规则验证(iview)

    一: 判断密码是否可见判断:type="visiblePassword ? 'text' : 'password'" 是否为false 或者 true 密码为输入框或者文本框点击眼 ...

  8. dfs 全排列 使用交换——含重复元素和非重复元素

    15. 全排列 中文 English 给定一个数字列表,返回其所有可能的排列. 样例 样例 1: 输入:[1] 输出: [ [1] ] 样例 2: 输入:[1,2,3] 输出: [ [1,2,3], ...

  9. mysql删除重复记录,只保留最大ID的记录(非重复也保留)

    目前网上搜索的删除重复记录,大部分都是where子查询,本人感觉看上去不美观,故亲自手写了一个,如下: delete from mst_sku using mst_sku,(  select dist ...

随机推荐

  1. Vue指令的概念

    指令(Directives) 是带有v- 前缀的特殊属性,指令属性是单一的js表达式. 指令的职责就是表达式的值发生变化时,在DOM中做出相应的回应. 如下例子: 实例 <div id=&quo ...

  2. linux mysql设置远程访问

    >mysql -u root -p 选择进入mysql数据库use `mysql`; 查看所有存在的账号和地址.SELECT `Host`,`User` FROM `user`; 现在决定让ro ...

  3. HDU - 6266 - HDU 6266 Hakase and Nano (博弈论)

    题意: 有两个人从N个石子堆中拿石子,其中一个人可以拿两次,第二个人只能拿一次.最后拿完的人胜利. 思路: 类型 Hakase先 Hakase后 1 W L 1 1 W W 1 1 1 (3n) L ...

  4. [Python数据结构] 使用 Circular List实现Queue

    [Python数据结构] 使用 Circular List实现Queue 1. Queue队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表.在具体 ...

  5. <MyBatis>入门六 动态sql

    package org.maple.mapper; import org.apache.ibatis.annotations.Param; import org.maple.pojo.Employee ...

  6. 移动端禁止滑动的js处理方式

    下面是禁止移动端滑动事件的方式,慎用  document.querySelector('body').addEventListener('touchmove', function (ev) {     ...

  7. CKplayer:视频推荐和分享插件设置

    如果想去掉播放结束后显示精彩视频推荐的插件,可以打开ckplayer.js和ckplayer.xml,找到以下代码,然后注释掉即可: control_rel: 'related.swf,ckplaye ...

  8. 常量Constant

    常量通常指的是一个固定的值,例如:1.2.3.’a’.’b’.true.false.”helloWorld”等. 在Java语言中,主要是利用关键字final来定义一个常量. 常量一旦被初始化后不能再 ...

  9. image url to base64

    image url to base64 https://www.base64-image.de/ https://www.browserling.com/tools/image-to-base64 h ...

  10. cookie & cookies

    cookie & cookies "use strict"; /** * * @author xgqfrms * @license MIT * @copyright xgq ...